<template>
  <div class="page_root" :key="queryUpdateFlag" data-page-name="平台任务" data-page-identification="h_t1xfr3f7sn">
    <a-spin :spinning="pageLoading.loading" :tip="pageLoading.tip">
      <!-- begin vid_6r73v1w6y0 自定义模板_2aqh9l752f -->
      <!-- begin vid_6r73v1w6y0 自定义模板_2aqh9l752f -->
      <!--            查看问题-->
      <a-modal
        :visible="showMsgState.visible"
        title="问题描述"
        :footer="null"
        centered
        @cancel="cancelShowMsg"
        width="1000px"
        :body-style="{
                    maxHeight: '800px',
                    overflowY: 'auto'
                }"
      >
        <div class="item-content" v-html="getHtmlContent(showMsgState.msg)"> </div>
      </a-modal>
      <!--            查看问题-->

      <!--          流转变更-->
      <a-modal
        centered
        v-model:visible="taskState.culaVisible"
        title="流转"
        width="520px"
        @ok="handleSubmitCirculation"
        destroy-on-close
        :body-style="{
                    paddingBottom: 0
                }"
        :ok-button-props="{
                    loading: taskState.culaLoading
                }"
        @cancel="cancelCirculation"
      >
        <div class="change-status">
          <a-row>
            <a-col :span="24">
              <a-form-item label="解决人" :rules="[{ required: true, message: '请选择解决人', trigger: 'blur' }]" name="solverList">
                <a-select
                  class="remove-icon"
                  show-search
                  :allow-clear="false"
                  :options="groupList"
                  v-model:value="taskState.culaPeople"
                  placeholder="请选择"
                  :field-names="{ label: 'label', value: 'value' }"
                  :filter-option="
                                        (input, option) => {
                                            return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                        }
                                    "
                />
              </a-form-item>
            </a-col>
          </a-row>
        </div>
      </a-modal>
      <!--          流转变更-->
      <!--审批详情-->
      <a-modal
        @cancel="statuState.visible = false"
        centered
        :visible="statuState.visible"
        title="审批详情"
        @ok="handleConfirmStatus"
        :body-style="{ maxHeight: '700px', overflowY: 'auto' }"
        width="400px"
      >
        <div style="margin-bottom: 16px"
          >任务名称：<span style="color: #262626">{{ statuState.taskName }}</span>
        </div>
        <a-radio-group v-model:value="statusRadio" button-style="solid" style="margin-bottom: 16px">
          <a-radio-button value="状态变更">状态变更</a-radio-button>
          <a-radio-button value="审批记录">审批记录</a-radio-button>
        </a-radio-group>
        <template v-if="statusRadio === '审批记录'">
          <div class="status-item" v-for="(item, index) in statuState.list">
            <div class="title-new-status">
              <div class="left-title"
                >审批类型:<span class="weight-status-new">{{ item.processName }} </span></div
              >
              <div class="right-title"
                >审批提交时间:<span class="weight-status-new">{{ item.createdDate }} </span></div
              >
            </div>
            <a-steps class="status-step" direction="vertical">
              <a-step
                v-for="(inside, index) in item.processTaskList"
                :title="inside.nodeMessage"
                :description="inside.taskName + ':' + inside.assignUserName"
                :status="getIconStatus(inside.nodeStatus)"
              />
            </a-steps>
          </div>
        </template>
        <template v-else>
          <div>
            <a-radio-group v-model:value="statusCheckList" style="margin-bottom: 16px">
              <a-row>
                <a-col :span="24" v-for="(item, index) in statusList">
                  <a-radio :value="item">{{ item }}</a-radio>
                </a-col>
              </a-row>
            </a-radio-group>
          </div>
        </template>
      </a-modal>

      <!--审批详情-->
      <!--         历史备注   -->
      <a-modal :visible="noteState.visibleNotes" title="历史备注" width="40vw" centered destroyOnClose :footer="null" :getContainer="getModalContainer" @cancel="noteState.visibleNotes = false">
        <a-table
          class="note-table"
          bordered
          rowKey="taskId"
          :customRow="customRow"
          :columns="noteState.notesColumns"
          :data-source="noteState.noteData.descriptionDataList"
          :pagination="false"
          :row-class-name="(_record, index) => (index % 2 === 1 ? 'table-striped' : null)"
        />
      </a-modal>
      <!--         历史备注   -->
      <!--                      模板项目-风险预警-->
      <a-modal v-model:visible="warnState.warringVisible" title="新增任务风险" @ok="handleTemplateRiskOk">
        <a-form :model="warnState.templateRisk" ref="templateRiskRef">
          <a-row>
            <a-col :span="24">
              <a-form-item label="任务名称" name="taskName" :rules="[{ required: true, message: '请输入任务名称', trigger: 'blur' }]">
                <a-input v-model:value="warnState.templateRisk.taskName" disabled :placeholder="inputHolder" />
              </a-form-item>
            </a-col>
            <a-col :span="24">
              <a-form-item label="风险描述" name="riskDescription" :rules="[{ required: true, message: '请输入风险描述', trigger: 'blur' }]">
                <a-input v-model:value="warnState.templateRisk.riskDescription" :placeholder="inputHolder" />
              </a-form-item>
            </a-col>
            <a-col :span="24">
              <a-form-item label="解决方案" name="solution" :rules="[{ required: true, message: '请输入解决方案', trigger: 'blur' }]">
                <a-input v-model:value="warnState.templateRisk.solution" :placeholder="inputHolder" />
              </a-form-item>
            </a-col>
          </a-row>
        </a-form>
      </a-modal>
      <!--                      end模板项目-风险预警-->
      <!--            提测/验收-->
      <a-modal :visible="taskState.checkVisible" :title="taskState.checkTitle" @ok="handleSubmitCheck" @cancel="cancelCheck" centered :ok-button-props="{ loading: taskState.checkLoading }">
        <div>请确认该任务是否需要{{ checkFlag }}</div>
        <div
          >提交{{ checkFlag }}后，手动编辑的状态将自动变更为{{
    checkFlag === '提测' ? '测试中' : '验收中'
          }}</div
        >
        <div>并且向{{ checkFlag === '提测' ? '测试经理' : '产品经理' }}发送通知</div>
      </a-modal>
      <!--            提测/验收-->
      <!-- 新-模板项目检查清单弹出框 -->
      <a-modal :visible="taskState.okMbVisible" title="完成任务" destroyOnClose centered width="40%" :getContainer="getModalContainer" @cancel="taskState.okMbVisible = false">
        <div style="border-bottom: 1px solid #d9d9d9; margin-bottom: 10px" v-if="taskState.ppmTemplateCheckList.length > 0 || taskState.sopList[0].contentList.length > 0">
          <!-- 完成标准 -->
          <div class="new-check" v-if="taskState.ppmTemplateCheckList.length > 0">
            <div class="label">审核标准</div>
          </div>
          <div class="checkbox-group" v-for="(item, index) in taskState.ppmTemplateCheckList" :key="index">
            <a-checkbox v-model:checked="item.selected">
              {{ item.content }}
            </a-checkbox>
          </div>
          <!--                        sop-->
          <div class="new-check" v-if="taskState.sopList[0].contentList.length > 0">
            <div class="label">SOP</div>
          </div>
          <div class="checkbox-group">
            <a-checkbox v-for="(msg, index) in taskState.sopList[0].contentList" :key="index" v-model:checked="msg.selected">
              {{ msg.msg }}
            </a-checkbox>
          </div>
          <!--                        sop-->
        </div>

        <template #footer>
          <a-button key="back" type="primary" @click="downLoadTemplate" v-if="currentOkTask.templateFlag === '是'">下载模板</a-button>
          <a-button key="back" @click="taskState.okMbVisible = false">取消</a-button>
          <a-button key="back" @click="handleSubmitSop" v-if="currentOkTask.templateFlag === '是'">暂存SOP</a-button>
          <a-button key="submit" type="primary" :loading="templateOkDisabled" @click="handlerTemplateOk">提交审批</a-button>
        </template>
        <a-spin :spinning="uploadLoading">
          <a-upload :file-list="taskState.fileList" :multiple="true" :before-upload="handlerUploadWc" @remove="handleRemoveWc" accept=".xlsx,.ppt,.pdf,.PDF, image/*, .docx, .rp, .xls">
            <a-button type="primary">
              <upload-outlined />
              上传
            </a-button>
          </a-upload>
          <span>支持格式：image/*,.xlsx,.xls,.docx,.rp,.ppt,.pptx,.pdf</span>
        </a-spin>
      </a-modal>
      <!-- 模板项目检查清单弹出框 -->
      <!--                  预览-->
      <a-modal v-model:visible="stateF.previewVisible" @cancel="handleCancel" width="1000px" title="图片预览" :footer="null">
        <div v-if="stateF.isImagePreview">
          <img :src="stateF.previewImage" alt="附件" style="width: 100%" />
        </div>
        <div v-else>
          <iframe :src="stateF.previewFileUrl" style="width: 100%; height: 500px"></iframe>
        </div>
      </a-modal>
      <!--                  预览-->
      <!--                  操作附件-->
      <a-modal :visible="showFileVisible" title="附件" :footer="null" @cancel="showFileCancel" centered :maskClosable="false">
        <div v-for="(item, index) in fileShowList" :key="index" class="file-item">
          <a-dropdown>
            <span style="overflow: hidden; white-space: nowrap; text-overflow: ellipsis; display: block" :title="item.name">
              {{ item.name }}
            </span>
            <template #overlay>
              <a-menu>
                <a-menu-item>
                  <a-button style="width: 100%" type="link" size="small" :disabled="!item.type.startsWith('image')" @click="previewAttachment(item)">预览</a-button>
                </a-menu-item>
                <a-menu-item>
                  <a-button style="width: 100%" type="link" size="small" @click="handlerDownload(item)">下载</a-button>
                </a-menu-item>
              </a-menu>
            </template>
          </a-dropdown>
        </div>
      </a-modal>
      <!--                  操作附件-->
      <!--          编辑任务-->
      <a-modal
        :visible="taskState.editTaskVisible"
        :title="taskState.editTaskTitle"
        centered
        width="1000px"
        @ok="confirmEditOtherMb"
        :ok-button-props="{ loading: taskState.editTaskLoading }"
        @cancel="cancelEditTask"
        destroy-on-close
      >
        <div class="mbtask-form">
          <a-form :model="taskState.editTaskForm" ref="ptOtherRef">
            <div v-for="(item, index) in taskState.editTaskForm.taskList" :key="index" class="form-item">
              <a-row>
                <a-col :span="24">
                  <a-form-item
                    label="任务名称"
                    :name="['taskList', index, 'taskName']"
                    :rules="[
                                            {
                                                required: true,
                                                message: '请输入任务名称!'
                                            },
                                            {
                                                validator: () => {
                                                    if (taskState.editTaskForm.taskList[index].taskName) {
                                                        if (taskState.editTaskForm.taskList[index].taskName.trim()) {
                                                            return PromiseProxy.resolve()
                                                        } else {
                                                            return PromiseProxy.reject('请输入任务名称!')
                                                        }
                                                    } else {
                                                        return PromiseProxy.resolve()
                                                    }
                                                }
                                            }
                                        ]"
                  >
                    <a-input :placeholder="inputHolder" v-model:value="taskState.editTaskForm.taskList[index].taskName" />
                  </a-form-item>
                </a-col>

                <a-col :span="24">
                  <a-form-item label="优先级" :name="['taskList', index, 'priority']" :rules="[{ required: true, msssage: '请选择优先级', trigger: 'blur' }]">
                    <a-select
                      :options="[
                                                {
                                                    label: 'P0',
                                                    value: 'P0'
                                                },
                                                {
                                                    label: 'P1',
                                                    value: 'P1'
                                                },
                                                {
                                                    label: 'P2',
                                                    value: 'P2'
                                                },
                                                {
                                                    label: 'P3',
                                                    value: 'P3'
                                                }
                                            ]"
                      v-model:value="taskState.editTaskForm.taskList[index].priority"
                    />
                  </a-form-item>
                </a-col>
              </a-row>
              <a-row>
                <a-col :span="12">
                  <a-form-item label="所属用户故事" :name="['taskList', index, 'storyId']" :rules="{ required: true, message: '请选择所属用户故事!' }">
                    <a-select
                      :placeholder="selectHolder"
                      v-model:value="taskState.editTaskForm.taskList[index].storyId"
                      showSearch
                      :options="taskState.storyList"
                      :field-names="{ label: 'label', value: 'value' }"
                      :filter-option="
                                                (input, option) => {
                                                    return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                }
                                            "
                      @focus="getStory"
                      @change="taskState.editTaskForm.taskList[index].parentId = undefined"
                    />
                  </a-form-item>
                </a-col>
                <a-col :span="12" v-if="currentOtherTask.taskId">
                  <a-form-item label="所属SOP任务">
                    <!--                                        :name="['taskList', index, 'parentId']" :rules="{ required: true, message:-->
                    <!--                                        '请选择父级任务!' }"-->
                    <a-tree-select
                      placeholder="请选择所属SOP任务"
                      v-model:value="taskState.editTaskForm.taskList[index].parentId"
                      allowClear
                      showSearch
                      :tree-data="taskState.editSopTaskList"
                      :field-names="{ label: 'taskName', value: 'taskId' }"
                      :filter-option="
                                                (input, option) => {
                                                    return (
                                                        option.taskName.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                    )
                                                }
                                            "
                      @focus="getEditSopTask"
                    />
                  </a-form-item>
                </a-col>
              </a-row>
              <a-row>
                <a-col :span="12">
                  <a-form-item
                    label="预计投入工时"
                    :name="['taskList', index, 'workingHours']"
                    :rules="[
                                            { required: true, message: '请输入预计投入工时!', trigger: 'blur' },
                                            {
                                                pattern: /^(0\.5|[1-9](\d*)?(\.5)?(\.0)?)$/,
                                                message: '请输入大于0的数字(支持0.5的倍数)',
                                                trigger: 'blur'
                                            }
                                        ]"
                  >
                    <a-input placeholder="请输入工时(支持0.5的数字)" v-model:value="taskState.editTaskForm.taskList[index].workingHours" :min="0" type="number" suffix="小时" />
                  </a-form-item>
                </a-col>
                <a-col :span="12">
                  <a-form-item label="任务起止时间" :name="['taskList', index, 'allTime']" :rules="{ required: true, message: '请选择任务起止时间!' }">
                    <a-range-picker style="width: 100%" v-model:value="taskState.editTaskForm.taskList[index].allTime" valueFormat="YYYY-MM-DD" />
                  </a-form-item>
                </a-col>
              </a-row>
              <a-row>
                <a-col :span="12">
                  <a-form-item label="任务负责人" :name="['taskList', index, 'taskOwner']" :rules="{ required: true, message: '请选择任务负责人!' }">
                    <a-select
                      :placeholder="selectHolder"
                      v-model:value="taskState.editTaskForm.taskList[index].taskOwner"
                      showSearch
                      :options="peopleList"
                      :field-names="{ label: 'label', value: 'value' }"
                      :filter-option="
                                                (input, option) => {
                                                    return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                }
                                            "
                    />
                  </a-form-item>
                </a-col>
                <a-col :span="12">
                  <a-form-item label="审核员" :name="['taskList', index, 'assessorName']" :rules="{ required: false, message: '请选择审核员!' }">
                    <a-select
                      :placeholder="selectHolder"
                      v-model:value="taskState.editTaskForm.taskList[index].assessorName"
                      showSearch
                      :options="peopleList"
                      :field-names="{ label: 'label', value: 'value' }"
                      :filter-option="
                                                (input, option) => {
                                                    return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                }
                                            "
                    />
                  </a-form-item>
                </a-col>
              </a-row>
              <a-row>
                <a-col :span="24">
                  <a-form-item label="任务执行人" :name="['taskList', index, 'taskParticipantList']" :rules="{ required: true, message: '请选择任务参与人!' }">
                    <a-select
                      :placeholder="selectHolder"
                      v-model:value="taskState.editTaskForm.taskList[index].taskParticipantList"
                      showSearch
                      mode="multiple"
                      :options="peopleList"
                      :field-names="{ label: 'label', value: 'value' }"
                      :filter-option="
                                                (input, option) => {
                                                    return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                }
                                            "
                    />
                  </a-form-item>
                </a-col>
              </a-row>
              <a-row>
                <a-col v-if="taskPeopleList.length > 0" :span="24">
                  <div style="width: 700px; margin-left: 115px; margin-bottom: 28px">
                    <a href="javascript:;" v-for="(item, num) in taskPeopleList" @click="handlerAddEditPeople(item.value, index)"
                      ><span style="margin: 0 5px">{{ item.value }}</span></a
                    >
                  </div>
                </a-col>
              </a-row>
              <a-row>
                <a-col :span="24">
                  <a-form-item label="备注">
                    <a-textarea placeholder="请输入备注" v-model:value="taskState.editTaskForm.taskList[index].description" />
                  </a-form-item>
                </a-col>
              </a-row>
            </div>
          </a-form>
        </div>
      </a-modal>
      <!--          编辑任务-->
      <!--          新建子任务-->
      <a-modal
        :visible="taskState.otherTaskVisible"
        :title="taskState.otherTaskTitle"
        centered
        width="1000px"
        @ok="confirmOtherMb"
        :ok-button-props="{ loading: taskState.otherOkLoading }"
        @cancel="cancelOtherMb"
        destroy-on-close
      >
        <div class="mbtask-form">
          <a-form :model="taskState.otherTaskForm" ref="ptOtherRef">
            <div v-for="(item, index) in taskState.otherTaskForm.taskList" :key="index" class="form-item">
              <a-row>
                <a-col :span="22">
                  <a-form-item
                    label="任务名称"
                    :name="['taskList', index, 'taskName']"
                    :rules="[
                                            {
                                                required: true,
                                                message: '请输入任务名称!'
                                            },
                                            {
                                                validator: () => {
                                                    if (taskState.otherTaskForm.taskList[index].taskName) {
                                                        if (taskState.otherTaskForm.taskList[index].taskName.trim()) {
                                                            return PromiseProxy.resolve()
                                                        } else {
                                                            return PromiseProxy.reject('请输入任务名称!')
                                                        }
                                                    } else {
                                                        return PromiseProxy.resolve()
                                                    }
                                                }
                                            }
                                        ]"
                  >
                    <a-input :placeholder="inputHolder" v-model:value="taskState.otherTaskForm.taskList[index].taskName" />
                  </a-form-item>
                </a-col>
                <a-col :span="2"><a-button type="link" @click="handleDeleteOtherItem(index)"> 删除</a-button> </a-col>
              </a-row>
              <a-row>
                <a-col :span="11">
                  <a-form-item label="所属用户故事" :name="['taskList', index, 'storyId']" :rules="{ required: true, message: '请选择所属用户故事!' }">
                    <a-select
                      :placeholder="selectHolder"
                      v-model:value="taskState.otherTaskForm.taskList[index].storyId"
                      showSearch
                      :options="taskState.storyList"
                      :field-names="{ label: 'label', value: 'value' }"
                      :filter-option="
                                                (input, option) => {
                                                    return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                }
                                            "
                      @focus="getStory"
                    />
                  </a-form-item>
                </a-col>
                <a-col :span="11">
                  <a-form-item label="所属SOP任务">
                    <!--                                        :name="['taskList', index, 'parentId']" :rules="{ required: true, message:-->
                    <!--                                        '请选择父级任务!' }"-->
                    <a-tree-select
                      placeholder="请选择所属SOP任务"
                      v-model:value="taskState.otherTaskForm.taskList[index].parentId"
                      allowClear
                      showSearch
                      :tree-data="taskState.otherTaskForm.taskList[index].sopTaskList"
                      :field-names="{ label: 'taskName', value: 'taskId' }"
                      :filter-option="
                                                (input, option) => {
                                                    return (
                                                        option.taskName.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                    )
                                                }
                                            "
                    />
                  </a-form-item>
                </a-col>
              </a-row>
              <a-col :span="22">
                <a-form-item label="优先级" :name="['taskList', index, 'priority']" :rules="[{ required: true, message: '请选择优先级', trigger: 'blur' }]">
                  <a-select
                    :options="[
                                            {
                                                label: 'P0',
                                                value: 'P0'
                                            },
                                            {
                                                label: 'P1',
                                                value: 'P1'
                                            },
                                            {
                                                label: 'P2',
                                                value: 'P2'
                                            },
                                            {
                                                label: 'P3',
                                                value: 'P3'
                                            }
                                        ]"
                    v-model:value="taskState.otherTaskForm.taskList[index].priority"
                  />
                </a-form-item>
              </a-col>
              <a-row>
                <a-col :span="11">
                  <a-form-item
                    label="预计投入工时"
                    :name="['taskList', index, 'workingHours']"
                    :rules="[
                                            { required: true, message: '请输入预计投入工时!', trigger: 'blur' },
                                            {
                                                pattern: /^(0\.5|[1-9](\d*)?(\.5)?(\.0)?)$/,
                                                message: '请输入大于0的数字(支持0.5的倍数)',
                                                trigger: 'blur'
                                            }
                                        ]"
                  >
                    <a-input placeholder="请输入工时(支持0.5的数字)" v-model:value="taskState.otherTaskForm.taskList[index].workingHours" :min="0" type="number" suffix="小时" />
                  </a-form-item>
                </a-col>
                <a-col :span="11">
                  <a-form-item label="任务起止时间" :name="['taskList', index, 'allTime']" :rules="{ required: true, message: '请选择任务起止时间!' }">
                    <a-range-picker style="width: 100%" v-model:value="taskState.otherTaskForm.taskList[index].allTime" valueFormat="YYYY-MM-DD" />
                  </a-form-item>
                </a-col>
              </a-row>
              <a-row>
                <a-col :span="11">
                  <a-form-item label="任务负责人" :name="['taskList', index, 'taskOwner']" :rules="{ required: true, message: '请选择任务负责人!' }">
                    <a-select
                      :placeholder="selectHolder"
                      v-model:value="taskState.otherTaskForm.taskList[index].taskOwner"
                      showSearch
                      :options="peopleList"
                      :field-names="{ label: 'label', value: 'value' }"
                      :filter-option="
                                                (input, option) => {
                                                    return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                }
                                            "
                    />
                  </a-form-item>
                </a-col>
                <a-col :span="11">
                  <a-form-item label="审核员" :name="['taskList', index, 'assessorName']" :rules="{ required: false, message: '请选择审核员!' }">
                    <a-select
                      :placeholder="selectHolder"
                      v-model:value="taskState.otherTaskForm.taskList[index].assessorName"
                      showSearch
                      :options="peopleList"
                      :field-names="{ label: 'label', value: 'value' }"
                      :filter-option="
                                                (input, option) => {
                                                    return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                }
                                            "
                    />
                  </a-form-item>
                </a-col>
              </a-row>
              <a-row>
                <a-col :span="22">
                  <a-form-item label="任务执行人" :name="['taskList', index, 'taskParticipantList']" :rules="{ required: true, message: '请选择任务参与人!' }">
                    <a-select
                      :placeholder="selectHolder"
                      v-model:value="taskState.otherTaskForm.taskList[index].taskParticipantList"
                      showSearch
                      mode="multiple"
                      :options="peopleList"
                      :field-names="{ label: 'label', value: 'value' }"
                      :filter-option="
                                                (input, option) => {
                                                    return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                                }
                                            "
                    />
                  </a-form-item>
                </a-col>
              </a-row>
              <a-row>
                <a-col v-if="taskPeopleList.length > 0" :span="22">
                  <div style="width: 700px; margin-left: 115px; margin-bottom: 28px">
                    <a href="javascript:;" v-for="(item, num) in taskPeopleList" @click="handlerAddOtherPeople(item.value, index)"
                      ><span style="margin: 0 5px">{{ item.value }}</span></a
                    >
                  </div>
                </a-col>
              </a-row>
              <a-row>
                <a-col :span="22">
                  <a-form-item label="备注">
                    <a-textarea placeholder="请输入备注" v-model:value="taskState.otherTaskForm.taskList[index].description" />
                  </a-form-item>
                </a-col>
              </a-row>
            </div>
            <a-col :span="22">
              <a-button @click="handleAddOtherItem" type="primary" ghost> 新增</a-button>
            </a-col>
          </a-form>
        </div>
      </a-modal>
      <!--          新建子任务-->
      <!--            新建sop任务-->
      <a-modal
        :visible="taskState.addOrEditVisible"
        :title="taskState.addOrEditTitle"
        centered
        :mask-closable="false"
        destroy-on-close
        :body-style="{
                    maxHeight: '800px',
                    overflowY: 'auto'
                }"
        width="1000px"
        @cancel="cancelStory"
      >
        <template #footer>
          <a-button type="primary" @click="cancleMbTask"> 取消</a-button>
          <a-button type="primary" v-if="taskState.current == 1" @click="getTask" :loading="taskState.nextLoading"> 下一步</a-button>
          <a-button type="primary" v-if="taskState.current == 2" @click="taskState.current = 1"> 上一步</a-button>
          <a-button type="primary" @click="confirmMbTask" v-if="taskState.current == 2" :loading="taskState.okLoading"> 确定</a-button>
        </template>
        <div class="form-model">
          <a-form :model="taskState.modalForm" ref="formRef" :rules="rules">
            <a-row v-if="taskState.current == 1">
              <a-col :span="24">
                <a-form-item label="用户故事名称" name="storyId">
                  <a-select
                    :placeholder="selectHolder"
                    v-model:value="taskState.modalForm.storyId"
                    showSearch
                    :options="taskState.storyList"
                    :field-names="{ label: 'label', value: 'value' }"
                    :filter-option="
                                            (input, option) => {
                                                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                    @focus="getStory"
                  />
                </a-form-item>
              </a-col>
              <a-col :span="24">
                <a-form-item label="功能简称" name="functionAbbreviation">
                  <a-input :placeholder="inputHolder" v-model:value="taskState.modalForm.functionAbbreviation" maxlength="10" show-count />
                </a-form-item>
              </a-col>
              <a-col :span="24">
                <a-form-item label="SOP任务" name="templateTaskId">
                  <a-tree-select
                    v-model:value="taskState.modalForm.templateTaskId"
                    show-search
                    multiple
                    treeCheckable
                    style="width: 100%"
                    placeholder="请选择"
                    allow-clear
                    treeDefaultExpandAll
                    :tree-data="taskState.treeData"
                    :fieldNames="{
                                            children: 'children',
                                            label: 'taskName',
                                            value: 'taskId',
                                            key: 'taskId'
                                        }"
                    :filterTreeNode="
                                            (inputValue, treeNode) => {
                                                return (
                                                    treeNode.taskName.toLowerCase().indexOf(inputValue.toLowerCase()) >=
                                                    0
                                                )
                                            }
                                        "
                    :max-tag-count="7"
                    @focus="getTreeData"
                  />
                </a-form-item>
              </a-col>
            </a-row>
            <div v-else>
              <div v-for="(item, index) in taskState.modalForm.taskList" :key="index" class="form-item">
                <div class="form-content">
                  <a-row class="one-line">
                    <a-col :span="24">
                      <a-form-item
                        label="任务名称"
                        :name="['taskList', index, 'taskName']"
                        :rules="[
                                                    {
                                                        required: true,
                                                        message: '请输入任务名称!'
                                                    },
                                                    {
                                                        validator: () => {
                                                            if (taskState.modalForm.taskList[index].taskName) {
                                                                if (
                                                                    taskState.modalForm.taskList[index].taskName.trim()
                                                                ) {
                                                                    return PromiseProxy.resolve()
                                                                } else {
                                                                    return PromiseProxy.reject('请输入任务名称!')
                                                                }
                                                            } else {
                                                                return PromiseProxy.resolve()
                                                            }
                                                        }
                                                    }
                                                ]"
                      >
                        <a-input disabled :placeholder="inputHolder" v-model:value="taskState.modalForm.taskList[index].taskName" />
                      </a-form-item>
                    </a-col>
                  </a-row>

                  <a-row>
                    <a-col :span="12">
                      <a-form-item
                        label="预计投入工时"
                        :name="['taskList', index, 'workingHours']"
                        :rules="[
                                                    { required: true, message: '请输入预计投入工时!', trigger: 'blur' },
                                                    {
                                                        pattern: /^(0\.5|[1-9](\d*)?(\.5)?(\.0)?)$/,
                                                        message: '请输入大于0的数字(支持0.5的倍数)',
                                                        trigger: 'blur'
                                                    }
                                                ]"
                      >
                        <a-input placeholder="请输入工时(支持0.5的数字)" v-model:value="taskState.modalForm.taskList[index].workingHours" :min="0" type="number" suffix="小时" />
                      </a-form-item>
                    </a-col>
                    <a-col :span="12">
                      <a-form-item label="任务起止时间" :name="['taskList', index, 'allTime']" :rules="{ required: true, message: '请选择任务起止时间!' }">
                        <a-range-picker style="width: 100%" v-model:value="taskState.modalForm.taskList[index].allTime" valueFormat="YYYY-MM-DD" />
                      </a-form-item>
                    </a-col>
                  </a-row>
                  <a-row>
                    <a-col :span="12">
                      <a-form-item label="任务负责人" :name="['taskList', index, 'taskOwner']" :rules="{ required: true, message: '请选择任务负责人!' }">
                        <a-select
                          :placeholder="selectHolder"
                          v-model:value="taskState.modalForm.taskList[index].taskOwner"
                          showSearch
                          :options="peopleList"
                          :field-names="{ label: 'label', value: 'value' }"
                          :filter-option="
                                                        (input, option) => {
                                                            return (
                                                                option.label
                                                                    .toLowerCase()
                                                                    .indexOf(input.toLowerCase()) >= 0
                                                            )
                                                        }
                                                    "
                        />
                      </a-form-item>
                    </a-col>
                    <a-col :span="12">
                      <a-form-item label="审核员" :name="['taskList', index, 'assessorName']" :rules="{ required: false, message: '请选择审核员!' }">
                        <a-select
                          :placeholder="selectHolder"
                          v-model:value="taskState.modalForm.taskList[index].assessorName"
                          showSearch
                          :options="peopleList"
                          :field-names="{ label: 'label', value: 'value' }"
                          :filter-option="
                                                        (input, option) => {
                                                            return (
                                                                option.label
                                                                    .toLowerCase()
                                                                    .indexOf(input.toLowerCase()) >= 0
                                                            )
                                                        }
                                                    "
                        />
                      </a-form-item>
                    </a-col>
                    <a-col :span="24">
                      <a-form-item label="优先级" :name="['taskList', index, 'priority']" :rules="[{ required: true, message: '请选择优先级', trigger: 'blur' }]">
                        <a-select
                          :options="[
                                                        {
                                                            label: 'P0',
                                                            value: 'P0'
                                                        },
                                                        {
                                                            label: 'P1',
                                                            value: 'P1'
                                                        },
                                                        {
                                                            label: 'P2',
                                                            value: 'P2'
                                                        },
                                                        {
                                                            label: 'P3',
                                                            value: 'P3'
                                                        }
                                                    ]"
                          v-model:value="taskState.modalForm.taskList[index].priority"
                        />
                      </a-form-item>
                    </a-col>
                  </a-row>
                  <a-row class="one-line">
                    <a-col :span="24">
                      <a-form-item label="任务执行人" :name="['taskList', index, 'taskParticipantList']" :rules="{ required: true, message: '请选择任务参与人!' }">
                        <a-select
                          :placeholder="selectHolder"
                          v-model:value="
                                                        taskState.modalForm.taskList[index].taskParticipantList
                                                    "
                          showSearch
                          mode="multiple"
                          :options="peopleList"
                          :field-names="{ label: 'label', value: 'value' }"
                          :filter-option="
                                                        (input, option) => {
                                                            return (
                                                                option.label
                                                                    .toLowerCase()
                                                                    .indexOf(input.toLowerCase()) >= 0
                                                            )
                                                        }
                                                    "
                        />
                      </a-form-item>
                    </a-col>
                  </a-row>
                  <a-row>
                    <a-col v-if="taskPeopleList.length > 0">
                      <div style="width: 700px; margin-left: 115px; margin-bottom: 28px">
                        <a href="javascript:;" v-for="(item, num) in taskPeopleList" @click="handlerAddPtMbPeople(item.value, index)"
                          ><span style="margin: 0 5px">{{ item.value }}</span></a
                        >
                      </div>
                    </a-col>
                  </a-row>
                  <a-row class="one-line">
                    <a-col :span="24">
                      <a-form-item label="备注">
                        <a-textarea v-model:value="taskState.modalForm.taskList[index].remark" />
                      </a-form-item>
                    </a-col>
                  </a-row>
                </div>
              </div>
            </div>
          </a-form>
        </div>
      </a-modal>
      <!--            新建sop任务-->
      <!--            新建问题-->
      <a-modal
        :visible="taskState.addOrEditQuestionVisible"
        :title="taskState.addOrEditQuestionTitle"
        centered
        destroy-on-close
        :mask-closable="false"
        @cancel="resetQuestion"
        @ok="questionSubmit"
        width="1000px"
        :body-style="{
                    maxHeight: '800px',
                    overflowY: 'auto'
                }"
        :ok-button-props="{ loading: taskState.questionLoading }"
      >
        <a-form :model="taskState.questionForm" ref="questionFormRef">
          <div class="question-form">
            <a-row>
              <a-col :span="24">
                <a-form-item label="用户故事" name="storyId" :rules="{ required: true, message: '请选择用户故事!' }">
                  <a-select
                    disabled
                    :placeholder="selectHolder"
                    v-model:value="taskState.questionForm.storyId"
                    showSearch
                    :options="taskState.storyList"
                    :field-names="{ label: 'label', value: 'value' }"
                    :filter-option="
                                            (input, option) => {
                                                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                    @focus="getStory"
                  />
                </a-form-item>
              </a-col>
              <a-col :span="12">
                <a-form-item label="任务">
                  <!--                                    treeCheckable-->
                  <a-tree-select
                    disabled
                    v-model:value="taskState.questionForm.parentId"
                    show-search
                    style="width: 100%"
                    placeholder="请选择"
                    allow-clear
                    treeDefaultExpandAll
                    :tree-data="taskState.questionTaskList"
                    :fieldNames="{
                                            children: 'children',
                                            label: 'taskName',
                                            value: 'taskId',
                                            key: 'taskId'
                                        }"
                    :filterTreeNode="
                                            (inputValue, treeNode) => {
                                                return (
                                                    treeNode.taskName.toLowerCase().indexOf(inputValue.toLowerCase()) >=
                                                    0
                                                )
                                            }
                                        "
                    @focus="getQuestionTask"
                  />
                </a-form-item>
              </a-col>
              <a-col :span="24">
                <a-form-item label="问题名称" name="taskName" :rules="{ required: true, message: '请输入问题名称!' }">
                  <a-input v-model:value="taskState.questionForm.taskName" :placeholder="inputHolder" />
                </a-form-item>
              </a-col>
              <a-col :span="24">
                <a-form-item label="问题描述" :rules="[{ required: true, message: '请输入问题描述', trigger: 'blur' }]" name="description">
                  <QuillEditor v-model:content="taskState.questionForm.description" ref="quillEditor" :options="editorOption" class="quill-editor" />
                </a-form-item>
              </a-col>
              <a-col :span="12">
                <a-form-item label="问题类型" :rules="[{ required: true, message: '请选择问题类型', trigger: 'blur' }]" name="problemType">
                  <a-select
                    :placeholder="selectHolder"
                    v-model:value="taskState.questionForm.problemType"
                    :options="taskState.problemList"
                    :field-names="{ label: 'label', value: 'label' }"
                    :filterOption="
                                            (input, option) => {
                                                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                  />
                </a-form-item>
              </a-col>
              <a-col :span="12">
                <a-form-item label="优先级" :rules="[{ required: true, message: '请选择优先级', trigger: 'blur' }]" name="priority">
                  <a-select
                    :options="[
                                            {
                                                label: 'P0',
                                                value: 'P0'
                                            },
                                            {
                                                label: 'P1',
                                                value: 'P1'
                                            },
                                            {
                                                label: 'P2',
                                                value: 'P2'
                                            },
                                            {
                                                label: 'P3',
                                                value: 'P3'
                                            }
                                        ]"
                    v-model:value="taskState.questionForm.priority"
                  />
                </a-form-item>
              </a-col>
              <a-col :span="12">
                <a-form-item label="版本">
                  <a-input v-model:value="taskState.questionForm.version" :placeholder="inputHolder" />
                </a-form-item>
              </a-col>
              <a-col :span="12">
                <a-form-item label="计划开始时间" :rules="[{ required: true, message: '请选择计划开始时间', trigger: 'blur' }]" name="startTime">
                  <a-date-picker style="width: 100%" v-model:value="taskState.questionForm.startTime" value-format="YYYY-MM-DD" />
                </a-form-item>
              </a-col>
              <a-col :span="12">
                <a-form-item label="计划完成时间" :rules="[{ required: true, message: '请选择计划完成时间', trigger: 'blur' }]" name="endTime">
                  <a-date-picker style="width: 100%" v-model:value="taskState.questionForm.endTime" value-format="YYYY-MM-DD" />
                </a-form-item>
              </a-col>
              <a-col :span="12">
                <a-form-item label="解决人" :rules="[{ required: true, message: '请选择解决人', trigger: 'blur' }]" name="taskParticipant">
                  <a-select
                    :placeholder="selectHolder"
                    :options="groupList"
                    :allowClear="true"
                    :dropdownMatchSelectWidth="true"
                    :showSearch="true"
                    :filterOption="
                                            (input, option) => {
                                                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                            }
                                        "
                    :max-tag-count="1"
                    :showArrow="true"
                    v-model:value="taskState.questionForm.taskParticipant"
                  />
                </a-form-item>
              </a-col>
            </a-row>
          </div>
        </a-form>
      </a-modal>
      <!--            新建问题-->
      <div class="body">
        <div class="top-search">
          <a-row :gutter="24">
            <a-col :span="6">
              <a-form-item label="检索任务名称" :label-col="{ span: 8 }" :wrapper-col="{ span: 16 }">
                <a-input v-model:value="taskState.searchForm.keywords" @change="debounceGetData" :placeholder="inputHolder" />
              </a-form-item>
            </a-col>
            <a-col :span="6">
              <a-form-item label="人员" :label-col="{ span: 5 }" :wrapper-col="{ span: 19 }">
                <a-select
                  :placeholder="selectHolder"
                  :options="peopleList"
                  :allowClear="true"
                  :dropdownMatchSelectWidth="true"
                  :showSearch="true"
                  :filterOption="
                                        (input, option) => {
                                            return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                        }
                                    "
                  :max-tag-count="1"
                  :showArrow="true"
                  v-model:value="taskState.searchForm.userName"
                  @change="getData"
                />
              </a-form-item>
            </a-col>
            <a-col :span="6">
              <a-form-item label="任务类型" :label-col="{ span: 7 }" :wrapper-col="{ span: 17 }">
                <a-select
                  :placeholder="selectHolder"
                  allow-clear
                  v-model:value="taskState.searchForm.taskType"
                  :options="[
                                        { label: 'SOP任务', value: 'SOP任务' },

                                        { label: '子任务', value: '子任务' },
                                        { label: '问题', value: '问题' }
                                    ]"
                  @change="getData"
                />
              </a-form-item>
            </a-col>
            <a-col :span="6">
              <a-form-item label="标签" :label-col="{ span: 5 }" :wrapper-col="{ span: 19 }">
                <a-select :placeholder="selectHolder" allow-clear v-model:value="taskState.searchForm.storyLabels" :options="taskState.labelList" @change="getData" />
              </a-form-item>
            </a-col>
          </a-row>
          <a-row :gutter="24">
            <a-col :span="12">
              <a-form-item label="用户故事  " :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
                <a-select
                  :placeholder="selectHolder"
                  :options="taskState.storyList"
                  :allowClear="true"
                  :dropdownMatchSelectWidth="true"
                  :showSearch="true"
                  :filterOption="
                                        (input, option) => {
                                            return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
                                        }
                                    "
                  :max-tag-count="1"
                  :showArrow="true"
                  v-model:value="taskState.searchForm.storyId"
                  @change="getData"
                  @focus="getStory"
                />
              </a-form-item>
            </a-col>
            <a-col :span="6">
              <a-form-item label="计划完成时间" :label-col="{ span: 7 }" :wrapper-col="{ span: 17 }">
                <a-range-picker style="width: 100%" v-model:value="taskState.searchForm.endTimeList" valueFormat="YYYY-MM-DD" @change="getData" />
              </a-form-item>
            </a-col>
            <a-col :span="4" />
            <a-col :span="2" style="display: flex; justify-content: end; align-items: start">
              <a-button @click="resetData" ghost type="primary"> 重置</a-button>
            </a-col>
          </a-row>
          <a-divider style="margin: 0 0 16px 0; background-color: #3875ff; opacity: 0.5" />

          <div class="table-top">
            <!--                        <div class="tip">任务详细信息</div>-->
            <div class="tab-body">
              <div v-for="(group, key) in tabsConfig" :key="key" class="tab-btn" :class="{ active: key === activeTopTab }" @click="onTopTabChange(key)">
                {{ group.label }}
              </div>
            </div>

            <a-space :size="12">
              <!-- 子级下拉筛选 -->
              <a-form-item label="" style="margin: 0">
                <a-select v-if="currentSubTabOptions.length" v-model:value="activeSubTab[activeTopTab]" :options="currentSubTabOptions" @change="onSubTabChange" />
              </a-form-item>
              <a-form-item label="排序" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }" style="margin: 0">
                <a-select :placeholder="selectHolder" :options="taskState.sortList" v-model:value="taskState.searchForm.directionField" @change="getData" allow-clear />
              </a-form-item>
              <a-button class="btn-opration" @click="handleAddSopTask" v-permission="'50001252_vid_wcf3s76l4c'" type="primary">新建SOP任务</a-button>
              <a-button class="btn-opration" @click="handleAddSonTask" v-permission="'50001252_vid_wcf3s76l4c'" type="primary">新建子任务</a-button>
              <a-button class="btn-opration" @click="handlerShowCheck" v-permission="'50001252_vid_azzpjat1q3'" type="primary" :loading="keyNoteLoading" v-if="taskState.showCheck">保存</a-button>
              <a-button class="btn-opration" @click="handlerShowCheck" v-permission="'50001252_vid_azzpjat1q3'" type="primary" :loading="keyNoteLoading" v-if="!taskState.showCheck"
                >关键路径任务</a-button
              >
              <a-button @click="handleExpendAll" type="primary">{{
          taskState.expendAll ? '全部收起' : '全部展开'
              }}</a-button>
            </a-space>
          </div>
        </div>

        <a-spin :spinning="taskState.dataLoading" tip="加载中">
          <div class="content">
            <div class="no-progress" v-if="taskState.dataList.length == 0">
              <div class="no-tip">
                <p class="message">暂无数据</p>
              </div>
            </div>
            <div class="story-item" :style="{  backgroundColor: getStatusColor(item.taskStatus) }" v-for="(item, index) in taskState.dataList" :key="item.id">
              <div class="story-title" @click="handleExpend(item)">
                <div v-if="taskState.showCheck">
                  <a-checkbox
                    @click.stop=""
                    :checked="item.keynote === '是'"
                    v-if="item.taskType !== '问题'"
                    @change="
                          val => {
                              item.keynote = val.target.checked ? '是' : '否'
                              modifiedKeynotes.set(item.taskId, item.keynote) // 记录用户对这个 taskId 的选择
                          }
                      "
                  />
                </div>

                <div>
                  <div style="display: flex;margin-bottom:4px;box-shadow: 0px 2px 6px #c1cddf;">
                    <div class="priority-tag" title="优先级" :style="{backgroundColor: getBgc(item.priority)}">{{ item.priority || "NO" }}</div>
                    <div title="任务类型" class="type-tag" :style="{ color: getTypeColor(item.taskType) }">{{ item.taskType || '暂无' }}</div>
                  </div>

                  <div
                    :style="{
                                  boxShadow:'0px 2px 6px #c1cddf',
                                  backgroundColor: getStatusColor(item.taskStatus),
                                  textAlign: 'right',
                                  display:'flex'
                              }"
                  >
                    <div class="status-tag" title="任务状态" @click.stop=" getTaskStatus( item.taskId, 0, item.milepostId, item.taskStatus, item.taskType, item )">{{ item.taskStatus || '暂无' }}</div>
                    <div
                      title="审批详情-变更"
                      style="padding:3px;border-left:1px solid #fff;background: #fff;"
                      @click.stop=" getTaskStatus( item.taskId, 0, item.milepostId, item.taskStatus, item.taskType, item )"
                    >
                      <div class="can-edit"></div>
                    </div>
                  </div>
                </div>

                <div class="title-left">
                  <div class="title-left-mains">
                    <div class="task-name" :title="item.taskName">{{ item.taskName }}</div>
                  </div>
                  <div class="title-left-tags">
                    <div class="tags-group" v-if="item.projectMonthlyGoal || !item.parentName">
                      <div class="target-icon"></div>
                      <div class="tags-label">所属子目标：</div>
                      <div class="tags-content">{{ item.projectMonthlyGoal || '无'}}</div>
                    </div>

                    <div class="tags-group" v-if="!item.projectMonthlyGoal && item.parentName">
                      <div class="target-icon"></div>
                      <div class="tags-label">所属SOP任务：</div>
                      <div class="tags-content">{{ item.parentName || '无'}}</div>
                    </div>
                    <div v-if="item.keynote === '是'" class="critical-path">「 &nbsp; · &nbsp; 关键路径 」</div>
                  </div>
                </div>
                <div class="title-right" @click.stop="">
                  <a-space>
                    <a-button size="small" type="link" ghost :loading="item.startLoading" v-if="!item.examPassTime" :disabled="openDisabled(item)" @click="handleOpen(item)">开始</a-button>
                    <div v-if="!item.examPassTime" style="width: 1px; height: 14px; background-color: #3875ff; margin: 0 4px"></div>
                    <a-popconfirm
                      title="确定恢复该问题?"
                      ok-text="确定"
                      cancel-text="取消"
                      @confirm="restore(item)"
                      @cancel="cancel"
                      :disabled="disabledRestore(item)"
                      v-if="
                                                (item.taskStatus === '完成' || item.taskStatus === '延期完成') &&
                                                !item.instanceId &&
                                                item.taskType === '问题'
                                            "
                    >
                      <a-button size="small" type="link" ghost @click="restore(item)" :disabled="disabledRestore(item)">恢复</a-button>
                    </a-popconfirm>
                    <div
                      v-if="
                                                (item.taskStatus === '完成' || item.taskStatus === '延期完成') &&
                                                !item.instanceId &&
                                                item.taskType === '问题'
                                            "
                      style="width: 1px; height: 14px; background-color: #3875ff; margin: 0 4px"
                    ></div>
                    <a-button size="small" type="link" ghost v-if="item.examPassTime" @click="beforeOkMb(item)" :disabled="disabledComplate(item)">完成</a-button>
                    <div v-if="item.examPassTime" style="width: 1px; height: 14px; background-color: #3875ff; margin: 0 4px"></div>
                    <a-button
                      size="small"
                      type="link"
                      v-if="
                                                item.taskType !== '问题' &&
                                                item.examPassTime &&
                                                item.taskStatus !== '完成' &&
                                                item.taskStatus !== '测试中' &&
                                                item.taskStatus !== '验收中' &&
                                                item.taskStatus !== '延期完成'
                                            "
                      ghost
                      :disabled="testImprovementDisabled(item)"
                      @click="handleCheck(item, '提测')"
                      >提测</a-button
                    >
                    <div
                      v-if="
                                                item.taskType !== '问题' &&
                                                item.examPassTime &&
                                                item.taskStatus !== '完成' &&
                                                item.taskStatus !== '测试中' &&
                                                item.taskStatus !== '验收中' &&
                                                item.taskStatus !== '延期完成'
                                            "
                      style="width: 1px; height: 14px; background-color: #3875ff; margin: 0 4px"
                    ></div>
                    <a-button
                      size="small"
                      type="link"
                      v-if="
                                                item.taskType === '问题' &&
                                                item.taskStatus !== '完成' &&
                                                item.taskStatus !== '延期完成'
                                            "
                      ghost
                      :disabled="isCirculationDisabled(item)"
                      @click="showCirculation(item, '流转')"
                      >流转</a-button
                    >
                    <div
                      v-if="
                                                item.taskType === '问题' &&
                                                item.taskStatus !== '完成' &&
                                                item.taskStatus !== '延期完成'
                                            "
                      style="width: 1px; height: 14px; background-color: #3875ff; margin: 0 4px"
                    ></div>
                    <a-button size="small" type="link" v-if="item.taskType !== '问题' && item.taskStatus === '测试中'" ghost :disabled="checkDisabled(item)" @click="handleCheck(item, '验收')"
                      >验收</a-button
                    >
                    <div v-if="item.taskType !== '问题' && item.taskStatus === '测试中'" style="width: 1px; height: 14px; background-color: #3875ff; margin: 0 4px"></div>
                    <a-button size="small" type="link" ghost @click="handleEditTask(item)" :disabled="disabledEditBtn(item.taskStatus)">编辑</a-button>
                    <div style="width: 1px; height: 14px; background-color: #3875ff; margin: 0 4px"></div>
                    <template v-if="item.taskType === 'SOP任务' || item.taskType === '子任务'">
                      <a-popconfirm
                        title="确定删除?"
                        ok-text="确定"
                        cancel-text="取消"
                        @confirm="confirmDeleteTask(item)"
                        @cancel="cancel"
                        :disabled="!(item.taskOwnerPermission || item.createPermission)"
                      >
                        <a-button size="small" type="link" ghost :disabled="!(item.taskOwnerPermission || item.createPermission)">删除任务</a-button>
                      </a-popconfirm>
                      <div
                        style="
                                                    width: 1px;
                                                    height: 14px;
                                                    background-color: #3875ff;
                                                    margin: 0 4px;
                                                "
                      ></div>
                    </template>
                    <template v-if="item.taskType === '问题'">
                      <a-popconfirm title="确定删除?" ok-text="确定" cancel-text="取消" @confirm="confirmDeleteQuestion(item)" @cancel="cancel" :disabled="!item.createPermission">
                        <a-button size="small" type="link" ghost :disabled="!item.createPermission">删除问题</a-button>
                      </a-popconfirm>
                    </template>
                    <a-button
                      v-permission="'50001252_vid_6fu420wh3s'"
                      size="small"
                      type="link"
                      ghost
                      :disabled="addQuestionDisabled(item)"
                      @click="handleAddQuestion(item)"
                      v-if="item.taskType !== '问题'"
                      >新建问题</a-button
                    >
                    <a-dropdown>
                      <template #overlay>
                        <a-menu @click="handleMenuClick">
                          <a-menu-item key="1">
                            <a-button size="small" type="link" @click="handlerWarning(item)"> 预警 </a-button>
                          </a-menu-item>
                          <a-menu-item key="2">
                            <a-button size="small" type="link" @click="handlerShowNotes(item)" v-permission="'50001252_vid_7zflzaojcs'"> 历史备注 </a-button>
                          </a-menu-item>
                        </a-menu>
                      </template>
                      <a-button size="small" type="link" v-if="item.taskType !== '问题'">
                        更多
                        <EllipsisOutlined style="rotate: 90deg; font-size: 14px; margin: 0" />
                      </a-button>
                    </a-dropdown>
                  </a-space>
                </div>
              </div>
              <div style="background:#fff;">
                <transition name="slide-fade">
                  <div v-show="item.expend">
                    <div class="item-icon" v-if="item.storyLabels && item.taskType !== '问题'">
                      <div v-for="(tag, index) in handlerGetSpace(item.storyLabels)" class="label-item"> <div class="label-img"></div>{{ tag }} </div>
                    </div>
                    <!--                  <div class="item-icon target-item">-->
                    <!--                    <div class="target-icon"></div>-->
                    <!--                    <div class="item-label">所属子目标：</div>-->
                    <!--                    <div class="item-content">{{ item.projectMonthlyGoal }}</div>-->
                    <!--                  </div>-->
                    <div class="item-icon target-item" v-if="item.storyName && item.taskType === '子任务'" style="padding-top: 0px">
                      <div class="story-icon"></div>
                      <div class="item-label">所属用户故事：</div>
                      <div class="item-content">{{ item.storyName }}</div>
                    </div>
                    <div class="story-content" v-if="item.taskType === 'SOP任务'">
                      <a-descriptions title="" bordered :column="4" size="small">
                        <!-- 所属用户故事独占一行 -->
                        <a-descriptions-item label="所属用户故事" :span="4">
                          <div class="item-content no-set" :title="item.storyName"
                            ><div class="story-icon"></div
                            >{{
                      item.storyName
                            }}</div
                          >
                        </a-descriptions-item>

                        <!-- 项目阶段和所属SOP任务各占一半，组成第二行 -->
                        <a-descriptions-item label="项目阶段" :span="2">
                          <div class="item-content" :title="item.milepostName">{{
                      item.milepostName
                          }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="所属SOP任务" :span="2">
                          <div class="item-content" :title="item.parentName">{{
                      item.parentName
                          }}</div>
                        </a-descriptions-item>

                        <!-- 其余字段每行4个，每个不设置span（即默认1） -->
                        <a-descriptions-item label="未关闭风险数">
                          <div class="item-content" :title="item.riskNumber" style="color: red">{{
                      item.riskNumber
                          }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="问题任务数">
                          <div class="item-content" :title="item.problemCount">{{
                      item.problemCount
                          }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="进行中的问题任务">
                          <div class="item-content" :title="item.runningProblemCount">{{
                      item.runningProblemCount
                          }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="附件模板">
                          <div v-if="item.attachmentTemplateList?.length > 0" class="item-content main-font under-line" @click="showMore(item.attachmentTemplateList)">查看</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="附件">
                          <div v-if="item.attachmentList?.length > 0" class="item-content main-font under-line" @click="showMore(item.attachmentList)">查看</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="计划开始">
                          <div class="item-content" :title="item.startTime">{{
                      item.startTime
                          }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="实际开始">
                          <div class="item-content" :title="item.examPassTime">{{
                      item.examPassTime
                          }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="计划完成">
                          <div class="item-content" :title="item.endTime">{{ item.endTime }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="实际完成">
                          <div class="item-content" :title="item.taskFinishTime">{{
                      item.taskFinishTime
                          }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="创建人">
                          <div class="item-content" :title="item.createBy">{{
                      item.createBy
                          }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="任务负责人">
                          <div class="item-content" :title="item.taskOwner">{{
                      item.taskOwner
                          }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="创建时间">
                          <div class="item-content" :title="item.createTime">{{
                      item.createTime
                          }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="计划工时">
                          <div class="item-content" :title="item.workingHours">{{
                      item.workingHours
                          }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="任务执行人">
                          <div class="item-content" :title="item.taskParticipant">{{
                      item.taskParticipant
                          }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="实际工时">
                          <div class="item-content" :title="item.actualWorkHours">{{
                      item.actualWorkHours
                          }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="审核标准">
                          <div class="item-content" :title="item.assessorStandard">{{
                      item.assessorStandard
                          }}</div>
                        </a-descriptions-item>
                      </a-descriptions>

                      <!-- 第一行 -->
                    </div>
                    <div class="story-content" v-if="item.taskType === '子任务'">
                      <a-descriptions bordered :column="4" size="small">
                        <!-- 第二行：两项，各占2列 -->
                        <a-descriptions-item label="项目阶段" :span="2">
                          <div class="item-content" :title="item.milepostName">{{
                      item.milepostName
                          }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="所属SOP任务" :span="2">
                          <div class="item-content" :title="item.parentName">{{
                      item.parentName
                          }}</div>
                        </a-descriptions-item>

                        <!-- 后续每行最多4项，各占1列 -->
                        <a-descriptions-item label="未关闭风险数">
                          <span style="color: red">
                            <div class="item-content" :title="item.riskNumber">{{
                                item.riskNumber
                            }}</div>
                          </span>
                        </a-descriptions-item>
                        <a-descriptions-item label="问题任务数">
                          <div class="item-content" :title="item.problemCount">{{
                      item.problemCount
                          }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="进行中的问题任务">
                          <div class="item-content" :title="item.runningProblemCount">{{
                      item.runningProblemCount
                          }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="附件模板">
                          <div
                            v-if="
                                                        item.attachmentTemplateList &&
                                                        item.attachmentTemplateList.length > 0
                                                    "
                            class="item-content main-font under-line"
                            @click="showMore(item.attachmentTemplateList)"
                          >
                            查看
                          </div>
                        </a-descriptions-item>

                        <a-descriptions-item label="附件">
                          <div v-if="item.attachmentList && item.attachmentList.length > 0" class="item-content main-font under-line" @click="showMore(item.attachmentList)"> 查看 </div>
                        </a-descriptions-item>
                        <a-descriptions-item label="计划开始">
                          <div class="item-content" :title="item.startTime">{{
                      item.startTime
                          }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="实际开始">
                          <div class="item-content" :title="item.examPassTime">{{
                      item.examPassTime
                          }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="计划完成">
                          <div class="item-content" :title="item.endTime">{{ item.endTime }}</div>
                        </a-descriptions-item>

                        <a-descriptions-item label="实际完成">
                          <div class="item-content" :title="item.taskFinishTime">{{
                      item.taskFinishTime
                          }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="创建人">
                          <div class="item-content" :title="item.createBy">{{
                      item.createBy
                          }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="任务负责人">
                          <div class="item-content" :title="item.taskOwner">{{
                      item.taskOwner
                          }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="创建时间">
                          <div class="item-content" :title="item.createTime">{{
                      item.createTime
                          }}</div>
                        </a-descriptions-item>

                        <a-descriptions-item label="计划工时">
                          <div class="item-content" :title="item.workingHours">{{
                      item.workingHours
                          }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="任务执行人">
                          <div class="item-content" :title="item.taskParticipant">{{
                      item.taskParticipant
                          }}</div>
                        </a-descriptions-item>
                        <a-descriptions-item label="实际工时">
                          <div class="item-content" :title="item.actualWorkHours">{{
                      item.actualWorkHours
                          }}</div>
                        </a-descriptions-item>
                      </a-descriptions>
                    </div>
                    <div class="story-content" v-if="item.taskType === '问题'">
                      <a-descriptions title="" bordered :column="4" size="small">
                        <a-descriptions-item label="所属用户故事" :span="4">
                          <div class="item-content no-set" :title="item.storyName">{{
                      item.storyName
                          }}</div></a-descriptions-item
                        >

                        <a-descriptions-item label="所属SOP任务" :span="2">
                          <div class="item-content" :title="item.sopName">{{
                      item.sopName
                          }}</div></a-descriptions-item
                        >
                        <a-descriptions-item label="所属子任务" :span="2">
                          <div class="item-content" :title="item.parentName">{{
                      item.parentName
                          }}</div></a-descriptions-item
                        >
                        <a-descriptions-item label="优先级">
                          <span style="color: red">
                            <div class="item-content" :title="item.priority">{{
                                item.priority
                            }}</div></span
                          >
                        </a-descriptions-item>

                        <a-descriptions-item label="附件">
                          <div v-if="item.attachmentList && item.attachmentList.length > 0" class="item-content main-font under-line" @click="showMore(item.attachmentList)"
                            >查看</div
                          ></a-descriptions-item
                        >
                        <a-descriptions-item label="计划开始">
                          <div class="item-content" :title="item.startTime">{{
                      item.startTime
                          }}</div></a-descriptions-item
                        >
                        <a-descriptions-item label="实际开始"
                          ><div class="item-content" :title="item.examPassTime">{{
                    item.examPassTime
                          }}</div></a-descriptions-item
                        >
                        <a-descriptions-item label="计划完成">
                          <div class="item-content" :title="item.endTime">{{
                      item.endTime
                          }}</div></a-descriptions-item
                        >
                        <a-descriptions-item label="实际完成">
                          <div class="item-content" :title="item.taskFinishTime">{{
                      item.taskFinishTime
                          }}</div></a-descriptions-item
                        >
                        <a-descriptions-item label="创建人">
                          <div class="item-content" :title="item.createBy">{{
                      item.createBy
                          }}</div></a-descriptions-item
                        >

                        <a-descriptions-item label="创建时间"
                          ><div class="item-content" :title="item.createTime">{{
                    item.createTime
                          }}</div></a-descriptions-item
                        >
                        <a-descriptions-item label="计划工时">
                          <div class="item-content" :title="item.workingHours">{{
                      item.workingHours
                          }}</div></a-descriptions-item
                        >

                        <a-descriptions-item label="实际工时"
                          ><div class="item-content" :title="item.actualWorkHours">{{
                    item.actualWorkHours
                          }}</div></a-descriptions-item
                        >
                        <a-descriptions-item label="解决人"
                          ><div class="item-content" :title="item.taskParticipant">{{
                    item.taskParticipant
                          }}</div></a-descriptions-item
                        >
                        <a-descriptions-item label="问题描述"
                          ><div v-if="item.description" class="item-content main-font under-line" @click="showQuestionMsg(item.description)">查看</div></a-descriptions-item
                        >
                      </a-descriptions>
                      <!-- 第一行 -->
                    </div>
                  </div>
                </transition>
              </div>
            </div>
          </div>
        </a-spin>
      </div>

      <!-- end vid_6r73v1w6y0 自定义模板_2aqh9l752f -->
      <!-- begin vid_rw9kkee3ys 容器_laje2xgr6f -->
      <al-box v-if="false" class="vid_rw9kkee3ys">
        <!-- begin vid_tpphoipqc8 关键路径 -->
        <a-button v-permission="'3000001022_vid_tpphoipqc8'" class="vid_tpphoipqc8"> 关键路径 </a-button>
        <!-- end vid_tpphoipqc8 关键路径 -->
        <!-- begin vid_uomosqlhjq 新建任务 -->
        <a-button v-permission="'3000001022_vid_uomosqlhjq'" class="vid_uomosqlhjq"> 新建任务 </a-button>
        <!-- end vid_uomosqlhjq 新建任务 -->
        <!-- begin vid_ylycxvprwt 新建问题 -->
        <a-button v-permission="'3000001022_vid_ylycxvprwt'" class="vid_ylycxvprwt"> 新建问题 </a-button>
        <!-- end vid_ylycxvprwt 新建问题 -->
      </al-box>
      <!-- end vid_rw9kkee3ys 容器_laje2xgr6f -->
    </a-spin>
  </div>
</template>
<script setup lang="tsx">
  import {
      h, ref, reactive, toRaw, markRaw, watch, computed,
      onBeforeMount, onMounted, onBeforeUnmount, onUnmounted, onActivated, onDeactivated
    } from "vue";
    import { useRoute, useRouter } from 'vue-router';
    const router = useRouter();
    const route = useRoute();
    import { get, post, put, del, request, requestWithHeaders } from '@/utils/http/Axios';
    import { cloneDeep, localGet, merge, getDifferenceArray, traversalTreeStructure, checkCaseCondition, renderStringInTemplate, handleBreadcrumbJump, throttle, permission, getComponentParamsValue } from '@/utils/index';
    import { isNullOrEmpty, isEmptyArr, isNullOrUnDef, isContained, isArray, isEmpty, isObject } from '@/utils/is';
    import dayjs from 'dayjs';
    import { getPagePcChartsDataSourceConvert } from '@/utils/chart';
    import { message, notification, Modal } from 'ant-design-vue'
    import { propertyFormatByNumber, propertyFormatByPercentage, propertyFormatByDate, parseSubFromDataList } from '@/utils/format';
    import colorTheme from '@/design/custom-theme.json';
    
    import UserTableRecords from '@/model/UserTableRecords';
    import { getAppBaseUrl } from '@/utils/index';
    import { sendToken } from "@/hooks/useIframeToken";
    import { useSystemStore } from "@/store/modules/system";
    const systemStore = useSystemStore();
    



      // 获取传入的流程ID和组件参数
      const props = defineProps({
            'processInstanceId': {
            type: [String,Number,Boolean],
            default: undefined,
        },
      'projectId': {
            type: [String,Number],
            default: undefined,
        },
      })
      const immediateWatch = (source, callback) => {
        watch(source, callback, {deep: true,immediate: true })
      }



  /* -------------------------- 属性定义 -------------------------- */

      const setTimeOutList = [];
      const pageLoading = reactive({
        loading: false,
        tip: undefined
      });
      const authInfo = localGet('app-user-store');




      // 处理校验
      const setSubFormName =(parentInfo, name)=>{
        return [parentInfo.parents, parentInfo.cycleIndex, name];
      }


  /* ========================== 属性定义 ========================== */


  /* -------------------------- 元素数据引用 -------------------------- */


  /* ========================== 元素数据引用 ========================== */


  /* -------------------------- 页面数据 -------------------------- */


  /* ========================== 页面数据 ========================== */



  /* -------------------------- 响应 -------------------------- */

  /* ========================== 响应 ========================== */


  /* -------------------------- 函数 -------------------------- */

  /* ========================== 函数 ========================== */


  /* -------------------------- 页面参数 -------------------------- */

    const pageParameter_state = reactive({
        'processInstanceId': props.processInstanceId ?? route.query.processInstanceId,
    })

  /* ========================== 页面参数 ========================== */


  /* -------------------------- 组件事件处理方法 -------------------------- */

    // ---------------------------- 组件数据同步 ----------------------------

    // ============================ 组件数据同步 ============================


  /* ========================== 组件事件处理方法 ========================== */


  /* -------------------------- 生命周期 -------------------------- */
  // 用于参数变更后重新执行自定义指令
      const queryUpdateFlag = ref(0);
      onMounted(() => { ;

    });

    onUnmounted(() => {
      // 销毁定时器
      setTimeOutList.forEach(({ repeat, timer }) => {
        repeat ?  clearInterval(timer): clearTimeout(timer);
      });
    });

  /* ========================== 生命周期 ========================== */


  /* -------------------------- 数据关联处理 -------------------------- */





  /* -------------------------- 表单数据同步 -------------------------- */
  /* ========================== 表单数据同步 ========================== */

  /* ========================== 数据关联处理 ========================== */


  /* -------------------------- 不同组件自定义的处理逻辑 -------------------------- */

  /* ========================== 不同组件自定义的处理逻辑 ========================== */


  // ================================定制化逻辑========================================
  const userInfoStorage = localStorage.getItem('al__USER_INFO')
      const taskLeader = JSON.parse(userInfoStorage)
      const { projectId } = props
      const useProjectId = ref()
      import { watchEffect } from 'vue'
      watchEffect(() => {
          if (props.projectId) {
              setTimeout(() => {
                  useProjectId.value = props.projectId
                  getTemplateCode()
                  getPopleList()
                  getAllJfPeople()
                  getData()
                  getProity()
                  getQuestionType()
                  getGroupPeople()
                  getStatusList()
                  getLabelList()
              }, 500)
          }
      })
      onMounted(() => {
          document.addEventListener('click', e => {
              const target = e.target as HTMLElement
              if (target.tagName === 'IMG' && target.classList.contains('previewable-image')) {
                  const imgUrl = target.getAttribute('src')
                  if (imgUrl) {
                      // 预览逻辑，如弹窗显示 imgUrl
                      previewImage(imgUrl)
                  }
              }
          })
      })
      function previewImage(url) {
          const imgWindow = window.open()
          if (imgWindow) {
              imgWindow.document.write(`<img src="${url}" style="max-width:100%"/>`)
          }
      }
      const inputHolder = '请输入'
      const selectHolder = '请选择'
      const taskState = reactive({
          searchForm: {
              userName: taskLeader.value.name,
              keywords: undefined,
              storyId: undefined,
              directionField: 'default_sort-desc',
              taskStatus: undefined,
              taskType: undefined,
              endTimeList: [],
              storyLabels: undefined
          },
          expendAll: false,
          dataList: [],
          labelList: [],
          sortList: [
              {
                  label: '默认',
                  value: 'default_sort-desc'
              },
              {
                  label: '创建时间正序',
                  value: 'created_time-asc'
              },
              {
                  label: '创建时间倒序',
                  value: 'created_time-desc'
              },
              {
                  label: '计划完成时间正序',
                  value: 'end_time-asc'
              },
              {
                  label: '计划完成时间倒序',
                  value: 'end_time-desc'
              },
              {
                  label: '计划开始时间正序',
                  value: 'start_time-asc'
              },
              {
                  label: '计划开始时间倒序',
                  value: 'start_time-desc'
              },
              {
                  label: '优先级正序',
                  value: 'priority-asc'
              },
              {
                  label: '优先级倒序',
                  value: 'priority-desc'
              }
          ],
          treeData: [], // 原始树形数据
          questionTaskList: [], // 问题人物选择
          flatData: [], // 转换成 flat 的数组（只用于 Transfer 用 key）
          targetKeys: [], // 右边已选 key
          selectedKeys: [], // 左边当前选中 key
          SopTaskList: [],
          milepostList: [],
          addOrEditVisible: false,
          editTaskVisible: false,
          dataLoading: false,
          addOrEditTitle: '',
          modalForm: {
              selectKeys: [],
              taskList: [],
              functionAbbreviation: undefined,
              storyId: undefined,
              templateTaskId: []
          },
          storyList: [],
          current: 1,
          nextLoading: false,
          otherTaskVisible: false,
          otherTaskTitle: '',
          otherOkLoading: false,
          otherTaskForm: {
              taskList: [
                  {
                      taskParticipantList: [],
                      allTile: [],
                      startTime: undefined,
                      endTime: undefined,
                      taskName: undefined,
                      workingHours: undefined,
                      taskOwner: taskLeader.value.name,
                      assessorName: taskLeader.value.name,
                      parentId: undefined,
                      storyId: undefined,
                      sopTaskList: []
                  }
              ]
          },
          editTaskForm: {
              taskList: []
          },
          // 编辑子任务的时候的所属sop任务列表
          editSopTaskList: [],
          editTaskTitle: '',
          editTaskLoading: false,
          okLoading: false,
          //     所属SOP任务
          parentListMap: [],
          addOrEditQuestionVisible: false,
          questionLoading: false,
          addOrEditQuestionTitle: '',
          questionForm: {
              storyId: undefined,
              parentId: undefined,
              taskName: undefined,
              description: undefined,
              problemType: undefined,
              priority: undefined,
              version: undefined,
              startTime: undefined,
              endTime: undefined,
              taskParticipant: undefined
          },
          problemList: [],
          proityList: [],
          ppmTemplateCheckList: [],
          CompletionCheckListCheckList: [],
          okMbVisible: false,
          fileList: [],
          sopList: [],
          statusList: [],
          //     提测验收
          checkVisible: false,
          checkLoading: false,
          checkTitle: '',
          culaVisible: false,
          culaLoading: false,
          showCheck: false,
          keyNoteLoading: false,
          culaPeople: undefined,
          searchValue: ''
      })
      const formRef = ref(null)
      const questionFormRef = ref(null)
      const rules = {
          storyId: [
              {
                  required: true,
                  message: '请选择用户故事名称',
                  trigger: 'blur'
              }
          ],
          templateTaskId: [
              {
                  required: true,
                  message: '请选择SOP任务',
                  trigger: 'blur'
              }
          ],
          allTime: [{ required: false, message: '请选择任务起止时间!', trigger: 'blur' }],
          functionAbbreviation: [{ required: true, message: '请输入功能简称', trigger: 'blur' }]
      }

      watch(
          () => taskState.otherTaskForm.taskList.map(item => item.storyId),
          (newList, oldList) => {
              newList.forEach((storyId, index) => {
                  // 只有当 storyId 有值并且与旧值不一致时才触发
                  if (storyId && storyId !== oldList?.[index]) {
                      taskState.otherTaskForm.taskList[index].parentId = undefined
                      get(`/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/get_sop_task/${storyId}`).then(
                          data => {
                              taskState.otherTaskForm.taskList[index].sopTaskList = data.data || []
                          }
                      )
                  }
              })
          },
          { deep: true, immediate: false }
      )

      function getEditSopTask() {
          get(
              `/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/get_sop_task/${taskState.editTaskForm.taskList[0].storyId}`
          ).then(data => {
              taskState.editSopTaskList = data.data || []
          })
      }
      function getLabelList() {
          get(`/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/story_labels/${useProjectId.value}`).then(
              data => {
                  taskState.labelList = data.data
              }
          )
      }

      // 新建弹窗
      function handleAddSopTask() {
          currentmubanTask.value = {}
          taskState.addOrEditVisible = true
          taskState.addOrEditTitle = '新建SOP任务'
      }
      function useDebounce(fn: (...args: any[]) => void, delay = 500) {
          let timer: ReturnType<typeof setTimeout> | null = null

          return function (...args: any[]) {
              if (timer) clearTimeout(timer)
              timer = setTimeout(() => {
                  fn(...args)
              }, delay)
          }
      }
      // 包一层防抖函数
      const debounceGetData = useDebounce(getData, 500)
      // 获取列表
      function getData() {
          taskState.expendAll = false
          taskState.dataLoading = true
          post('/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/list', {
              'projectId': useProjectId.value,
              ...taskState.searchForm,
              taskStatusList: filterStatus.value
          })
              .then(data => {
                  if (data.code !== 200) {
                      message.error(data.message)
                      taskState.dataList = []
                      return
                  }
                  taskState.dataList = data.data.map(item => {
                      return {
                          ...item,
                          expend: false
                      }
                  })
                  initKeynotes(taskState.dataList)
              })
              .finally(() => {
                  taskState.dataLoading = false
              })
      }
      function handleExpend(item) {
          item.expend = !item.expend
      }
      // 重置
      function resetData() {
          taskState.searchForm = {
              userName: undefined,
              keywords: undefined,
              storyId: undefined,
              directionField: 'default_sort-desc',
              // taskStatus: undefined,
              taskType: undefined,
              endTimeList: [],
              storyLabels: undefined
          }
          getData()
      }
      //     新建下一步获取任务
      function getTask() {
          formRef.value.validate().then(() => {
              taskState.nextLoading = true
              post('/solution-ppm/api/v2/built-in-system-ppm/v2/platform/generate_task', {
                  templateTaskId: taskState.modalForm.templateTaskId,
                  storyId: taskState.modalForm.storyId,
                  functionAbbreviation: taskState.modalForm.functionAbbreviation,
                  projectId: useProjectId.value
              })
                  .then(data => {
                      taskState.current = 2
                      taskState.modalForm.taskList = data.data.map(item => {
                          return {
                              ...item,
                              allTime: [item.startTime, item.endTime]
                          }
                      })
                  })
                  .finally(() => {
                      taskState.nextLoading = false
                  })
          })
      }
      const taskPeopleList = ref([])
      function getPopleList() {
          post(`/solution-ppm/api/v2/built-in-system-ppm/task/getTopUser/${useProjectId.value}`).then(data => {
              taskPeopleList.value = data.data.map(item => {
                  return {
                      label: item,
                      value: item
                  }
              })
          })
      }
      // 快捷添加执行人
      function handlerAddPtMbPeople(name, index) {
          if (taskState.modalForm.taskList[index].taskParticipantList.indexOf(name) !== -1) {
              taskState.modalForm.taskList[index].taskParticipantList = taskState.modalForm.taskList[
                  index
              ].taskParticipantList.filter(item => item !== name)
          } else {
              taskState.modalForm.taskList[index].taskParticipantList.push(name)
          }
      }
      function cancelStory() {
          taskState.addOrEditVisible = false
      }
      const colorMap = {
          '进行中': '#3875FF',
          '审批中': '#1890FF',
          '未启动': '#BBBBBB',
          '完成': '#52C41A',
          '延期完成': '#FA8C16',
          '测试中': '#A0D911',
          '延期': '#FA3D16',
          '提测': '#A0D911',
          '验收': '#9254DE'
      }
      const typeColorMap = {
          'SOP任务': '#FF85C0',
          '子任务': '#FF85C0',
          '问题': '#FF85C0'
      }
      function getStatusColor(status) {
          return colorMap[status] || '#9DBAFF'
      }
      function getTypeColor(status) {
          return typeColorMap[status] || '#3875ff'
      }
      const peopleList = ref([])

      function getAllJfPeople() {
          get('/solution-ppm/api/v2/built-in-system-ppm/pmgf/get/allUser').then(({ data }) => {
              peopleList.value = data.userDtoList.map(item => {
                  return {
                      label: item.name,
                      value: item.name
                  }
              })
          })
      }
      const currentmubanTask = ref({})
      const currentOkTask = ref({})
      const currentOtherTask = ref({})
      function handleAddSonTask() {
          currentOtherTask.value = {}
          taskState.otherTaskVisible = true
          taskState.otherTaskForm = {
              taskList: [
                  {
                      taskParticipantList: [],
                      allTile: [],
                      startTime: undefined,
                      endTime: undefined,
                      taskName: undefined,
                      workingHours: undefined,
                      taskOwner: taskLeader.value.name,
                      assessorName: taskLeader.value.name,
                      parentId: undefined,
                      storyId: undefined,
                      taskId: undefined,
                      description: undefined,
                      sopTaskList: []
                  }
              ]
          }
          currentmubanTask.value = {}
          currentOtherTask.value = {}
          taskState.otherTaskTitle = '新建子任务'
      }
      const otherItem = {
          taskParticipantList: [],
          allTile: [],
          startTime: undefined,
          endTime: undefined,
          taskName: undefined,
          workingHours: undefined,
          taskOwner: taskLeader.value.name,
          assessorName: taskLeader.value.name,
          parentId: undefined,
          storyId: undefined,
          taskId: undefined,
          description: undefined
      }

      const projectTemplate = ref(null)
      function getTemplateCode() {
          get(`/solution-ppm/api/v2/built-in-system-ppm/project/${useProjectId.value}`).then(data => {
              projectTemplate.value = data.projectTemplate
          })
      }

      //     获取穿梭框
      function getTreeData() {
          get(
              `/solution-ppm/api/v2/built-in-system-ppm/v2/platform/template_milepost_task?templateCode=${projectTemplate.value}&projectId=${useProjectId.value}`
          ).then(data => {
              taskState.treeData = data.data
              // flatten(JSON.parse(JSON.stringify(taskState.treeData)))
              taskState.modalForm.selectKeys = []
          })
      }
      //
      // 获取用户故事
      function getStory() {
          post('/solution-ppm/api/v2/built-in-system-ppm/project/story/search', {
              projectId: useProjectId.value
          }).then(data => {
              taskState.storyList = data.data.map(item => {
                  return {
                      label: item.storyName,
                      value: item.id
                  }
              })
          })
      }
      // 保存模板项目
      function confirmMbTask() {
          formRef.value.validate().then(() => {
              taskState.okLoading = true
              taskState.modalForm.taskList.forEach(item => {
                  item.startTime = item.allTime[0]
                  item.endTime = item.allTime[1]
              })

              post(
                  `/solution-ppm/api/v2/built-in-system-ppm/v2/platform/batch_add_template_task/${useProjectId.value}`,
                  taskState.modalForm.taskList
              )
                  .then(data => {
                      if (data.code !== 200) {
                          message.error(data.message)
                          return
                      }
                      message.success('创建成功，请及时关联月度目标，保证目标甘特图数据准确')

                      cancleMbTask()

                      getData()
                  })
                  .finally(() => {
                      taskState.okLoading = false
                  })
          })
      }
      // 关闭模板任务新建
      function cancleMbTask() {
          taskState.addOrEditVisible = false
          taskState.current = 1
          taskState.modalForm.functionAbbreviation = undefined
          taskState.modalForm.templateTaskId = undefined
          taskState.modalForm = {
              templateTaskId: undefined,
              projectId: useProjectId.value,
              functionAbbreviation: undefined,
              taskList: []
          }
      }
      const PromiseProxy = Promise
      function handlerAddOtherPeople(name, index) {
          if (taskState.otherTaskForm.taskList[index].taskParticipantList.indexOf(name) !== -1) {
              taskState.otherTaskForm.taskList[index].taskParticipantList = taskState.otherTaskForm.taskList[
                  index
              ].taskParticipantList.filter(item => item !== name)
          } else {
              taskState.otherTaskForm.taskList[index].taskParticipantList.push(name)
          }
      }
      function handlerAddEditPeople(name, index) {
          if (taskState.editTaskForm.taskList[index].taskParticipantList.indexOf(name) !== -1) {
              taskState.editTaskForm.taskList[index].taskParticipantList = taskState.editTaskForm.taskList[
                  index
              ].taskParticipantList.filter(item => item !== name)
          } else {
              taskState.editTaskForm.taskList[index].taskParticipantList.push(name)
          }
      }
      function handleAddOtherItem() {
          taskState.otherTaskForm.taskList.push({ ...otherItem })
      }
      const ptOtherRef = ref(null)
      // 保存其他任务
      function confirmOtherMb() {
          ptOtherRef.value.validate().then(() => {
              taskState.otherOkLoading = true

              //   新建
              taskState.otherTaskForm.taskList.forEach(item => {
                  item.startTime = item.allTime[0]
                  item.endTime = item.allTime[1]
              })
              post(`/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/child_task/${useProjectId.value}`, {
                  dataList: taskState.otherTaskForm.taskList
              })
                  .then(data => {
                      if (data.code !== 200) {
                          message.error(data.message)
                          return
                      }
                      message.success(data.message)
                      cancelOtherMb()
                      getData()
                  })
                  .finally(() => {
                      taskState.otherOkLoading = false
                  })
          })
      }
      // 编辑任务保存
      function confirmEditOtherMb() {
          ptOtherRef.value.validate().then(() => {
              taskState.editTaskLoading = true
              taskState.editTaskForm.taskList.forEach(item => {
                  item.startTime = item.allTime[0]
                  item.endTime = item.allTime[1]
              })

              put(`/solution-ppm/api/v2/built-in-system-ppm/v2/platform/task`, {
                  ...taskState.editTaskForm.taskList[0],
                  projectId: useProjectId.value
              })
                  .then(data => {
                      if (data.code !== 200) {
                          message.error(data.message)
                          return
                      }
                      message.success('编辑成功')
                      getData()
                      currentOtherTask.value = {}
                      cancelEditTask()
                  })
                  .finally(() => {
                      taskState.editTaskLoading = false
                  })
          })
      }
      // 关闭其他任务新建
      function cancelOtherMb() {
          taskState.otherTaskVisible = false
          taskState.otherTaskForm = {
              taskList: [
                  {
                      taskParticipantList: [],
                      allTile: [],
                      startTime: undefined,
                      endTime: undefined,
                      taskName: undefined,
                      workingHours: undefined,
                      taskOwner: taskLeader.value.name,
                      assessorName: taskLeader.value.name,
                      parentId: undefined,
                      storyId: undefined,
                      taskId: undefined,
                      description: undefined,
                      sopTaskList: []
                  }
              ]
          }
          currentmubanTask.value = {}
          currentOtherTask.value = {}
      }
      // 关闭修改
      function cancelEditTask() {
          taskState.editTaskVisible = false
          currentmubanTask.value = {}
          currentOtherTask.value = {}
          currentQuestion.value = {}
      }

      function handleDeleteOtherItem(index) {
          taskState.otherTaskForm.taskList.splice(index, 1)
      }
      async function handleEditTask(item) {
          if (item.taskFinishTime) {
              message.info('已完成的任务不支持编辑')
              return
          } else if (item.taskStatus === '审批中') {
              message.info('审批中的任务不支持编辑')
              return
          }
          const record = cloneDeep(item)
          if (item.taskType === 'SOP任务' || item.taskType === '子任务') {
              if (item.taskType === 'SOP任务') {
                  currentmubanTask.value = record
              } else if (item.taskType === '子任务') {
                  currentOtherTask.value = record
              }
              taskState.editTaskForm.taskList[0] = {
                  ...item,
                  parentId: record.parentId === 0 ? undefined : record.parentId // 显式赋值
              }
              taskState.editTaskForm.taskList[0].allTime = [record.startTime, record.endTime]
              getStory()
              // if (item.taskType === '子任务') {
              //
              // }
              getEditSopTask()
              taskState.editTaskVisible = true
              taskState.editTaskTitle = `编辑${item.taskType}`
          } else {
              currentQuestion.value = record
              taskState.addOrEditQuestionVisible = true
              taskState.addOrEditQuestionTitle = '编辑问题任务'
              Object.assign(taskState.questionForm, record)
              await getStory()
              await getQuestionTask()
              nextTick(() => {
                  let descriptionData = JSON.parse(record.description)
                  quillEditor.value.setContents(descriptionData)
              })
          }
      }
      //     问题
      //     富文本设置
      import { nextTick } from 'vue'
      import { QuillEditor, Quill } from '@vueup/vue-quill'
      import ImageUploader from 'quill-image-uploader'
      import '@vueup/vue-quill/dist/vue-quill.snow.css'
      import { take } from 'lodash-es'
      const titleConfig = [
          { Choice: ' .ql-bold', title: '加粗' },
          { Choice: ' .ql-italic', title: '斜体' },
          { Choice: ' .ql-underline', title: '下划线' },
          { Choice: ' .ql-strike', title: '删除线' },
          { Choice: ' .ql-blockquote', title: '块引用' },
          { Choice: ' .ql-code-block', title: '插入代码' },
          { Choice: ' .ql-size', title: '字体大小' },
          { Choice: ' .ql-size', title: '字体大小' },
          { Choice: ' .ql-color', title: '字体颜色' },
          { Choice: ' .ql-background', title: '字体背景颜色' },
          { Choice: ' .ql-list[value="ordered"]', title: '有序列表' },
          { Choice: ' .ql-list[value="bullet"]', title: '无序列表' },
          { Choice: ' .ql-header[value="1"]', title: '1级标题' },
          { Choice: ' .ql-header[value="2"]', title: '2级标题' },
          { Choice: ' .ql-align', title: '对齐方式' },
          { Choice: ' .ql-clean', title: '清除字体格式' },
          { Choice: ' .ql-image', title: '图像' },
          { Choice: ' .ql-size .ql-picker-item[data-value="small"]', title: '小号' },
          { Choice: ' .ql-size .ql-picker-item[data-value="large"]', title: '大号' },
          { Choice: ' .ql-size .ql-picker-item[data-value="huge"]', title: '超大号' },
          { Choice: ' .ql-size .ql-picker-item:nth-child(2)', title: '标准' },
          { Choice: ' .ql-align .ql-picker-item:first-child', title: '居左对齐' },
          { Choice: ' .ql-align .ql-picker-item[data-value="center"]', title: '居中对齐' },
          { Choice: ' .ql-align .ql-picker-item[data-value="right"]', title: '居右对齐' },
          { Choice: ' .ql-align .ql-picker-item[data-value="justify"]', title: '两端对齐' }
      ]
      // 注册图片上传模块
      Quill.register('modules/imageUploader', ImageUploader)

      // 将本地文件转换为URL
      const getLocalImageURL = file => {
          return new Promise(resolve => {
              const reader = new FileReader()
              reader.onload = e => {
                  resolve(e.target.result)
              }
              reader.readAsDataURL(file)
          })
      }

      // 表单数据

      // Quill 编辑器选项
      const editorOption = ref({
          modules: {
              // imageUploader: {
              //     upload: async file => {
              //         const localUrl = await getLocalImageURL(file)
              //         return localUrl // 返回本地图片的 URL 进行预览
              //     }
              // },
              toolbar: [
                  ['bold', 'italic', 'underline', 'strike'], // 加粗，斜体，下划线，删除线
                  ['blockquote', 'code-block'], // 引用，代码块
                  [{ header: 1 }, { header: 2 }], // 标题1，标题2
                  [{ list: 'ordered' }, { list: 'bullet' }], // 有序列表，无序列表
                  [{ size: ['small', false, 'large', 'huge'] }], // 文字大小
                  [{ color: [] }, { background: [] }], // 字体颜色，背景颜色
                  [{ align: [] }], // 对齐
                  ['clean'], // 清除格式
                  ['image'] // 链接，图片，视频
              ]
              // ImageUploader: imageHandler
          }
      })
      // 上传API
      const uploadFileAPI = async file => {
          const data = new FormData()
          data.append('file', file)

          return post('/file-storage/api/v1/file/upload', data)
              .then(({ data: { fullUrl } }) => {
                  return { data: { fullUrl } }
              })
              .catch(error => {
                  console.error('上传图片出错:', error)
                  throw error // 抛出错误以供外部处理
              })
      }

      // 将 dataURL 转换为 File 对象的辅助函数
      const dataURLtoFile = (dataurl, filename) => {
          const arr = dataurl.split(',')
          const mime = arr[0].match(/:(.*?);/)[1]
          const bstr = atob(arr[1])
          let n = bstr.length
          const u8arr = new Uint8Array(n)
          while (n--) {
              u8arr[n] = bstr.charCodeAt(n)
          }
          return new File([u8arr], filename, { type: mime })
      }

      function initTitle() {
          document.getElementsByClassName('ql-editor')[0].dataset.placeholder = ''
          for (let item of titleConfig) {
              let tip = document.querySelector('.ql-toolbar' + item.Choice)
              if (!tip) continue
              tip.setAttribute('title', item.title)
          }
      }
      const currentQuestion = ref({})
      //     父工单提交表单
      function questionSubmit() {
          questionFormRef.value.validate().then(async () => {
              taskState.questionLoading = true
              const deltaContent = quillEditor.value.getContents()

              const imageUploadPromises = []

              deltaContent.ops.forEach(op => {
                  if (op.insert && op.insert.image && op.insert.image.startsWith('data:')) {
                      const localSrc = op.insert.image

                      // 如果是 base64 图片，上传并替换为 URL
                      const file = dataURLtoFile(localSrc, 'image.png') // 将 base64 转换为 File 对象

                      const uploadPromise = uploadFileAPI(file).then(({ data: { fullUrl } }) => {
                          // 替换 op 中的 base64 URL 为服务器返回的 URL
                          op.insert.image = fullUrl
                      })

                      imageUploadPromises.push(uploadPromise)
                  }
              })
              try {
                  await Promise.all(imageUploadPromises)
                  if (currentQuestion.value.taskId) {
                      // 编辑保存逻辑
                      const params = { ...taskState.questionForm }
                      params.description = JSON.stringify(deltaContent)
                      put('/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/problem', {
                          projectId: useProjectId.value,
                          ...params
                      })
                          .then(data => {
                              if (data.code !== 200) {
                                  message.error(data.message)
                                  return
                              }
                              message.success(data.message)
                              taskState.addOrEditVisible = false
                              resetQuestion()
                              getData()
                          })
                          .finally(() => {
                              taskState.questionLoading = false
                          })
                  } else {
                      // 新建保存逻辑
                      const params = { ...taskState.questionForm }
                      params.description = JSON.stringify(deltaContent)
                      post('/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/problem', {
                          projectId: useProjectId.value,
                          ...params
                      })
                          .then(data => {
                              if (data.code !== 200) {
                                  message.error(data.message)
                                  return
                              }
                              message.success(data.message)
                              taskState.addOrEditVisible = false
                              resetQuestion()
                              getData()
                          })
                          .finally(() => {
                              taskState.questionLoading = false
                          })
                  }
              } catch (error) {
                  taskState.questionLoading = false
                  console.error('图片上传失败', error)
                  return // 终止提交
              }
          })
      }
      const quillEditor = ref(null)
      function resetQuestion() {
          taskState.addOrEditQuestionVisible = false
          taskState.questionForm = {
              storyId: undefined,
              parentId: undefined,
              taskName: undefined,
              description: undefined,
              problemType: undefined,
              priority: undefined,
              version: undefined,
              startTime: undefined,
              endTime: undefined,
              taskParticipant: undefined
          }
          currentQuestion.value = {}
      }
      function handleAddQuestion(record) {
          const item = cloneDeep(record)
          taskState.addOrEditQuestionTitle = '新建问题'
          taskState.questionForm.storyId = item.storyId
          taskState.questionForm.parentId = item.taskId
          getStory()
          getQuestionTask()
          taskState.addOrEditQuestionVisible = true
          nextTick(() => {
              initTitle()
              quillEditor.value.setContents('')
          })
      }
      //     获取问题任务
      function getQuestionTask() {
          post('/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/list', {
              'projectId': useProjectId.value
          }).then(data => {
              taskState.questionTaskList = data.data
          })
      }
      const groupList = ref([])
      //     获取用户组成员
      function getGroupPeople() {
          get(
              `/solution-ppm/api/v2/built-in-system-ppm/delivery_project/internalCommunicationRecord/${useProjectId.value}/participants`
          ).then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  return
              }
              groupList.value = data.data.map(item => {
                  return {
                      label: item,
                      value: item
                  }
              })
          })
      }
      function getQuestionType() {
          get('/solution-ppm/api/v2/built-in-system-ppm/dictionary/search/PTRW.WTLX').then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  return
              }
              taskState.problemList = data.data.map(item => {
                  return {
                      label: item.itemName,
                      value: item.itemCode
                  }
              })
          })
      }
      function getProity() {
          get('/solution-ppm/api/v2/built-in-system-ppm/dictionary/search/PTRW.YXJ').then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  return
              }
              taskState.proityList = data.data.map(item => {
                  return {
                      label: item.itemName,
                      value: item.itemCode
                  }
              })
          })
      }
      // 关键路径任务
      const onKeynoteChange = (item, e) => {
          item.keynote = e.target.checked ? '是' : '否'

          // 统计所有 keynote 为 '是' 的 taskId
          const selectedIds = taskState.dataList.filter(task => task.keynote === '是').map(task => task.taskId) // 或 task.id，按你实际字段名

          // 这里调接口
          updateKeynoteList(selectedIds)
      }
      const updateKeynoteList = taskIdList => {
          // 发送请求给后端
          // 提交
          put(`/solution-ppm/api/v2/built-in-system-ppm/v2/platform/keynote_task/${useProjectId.value}`, taskIdList).then(
              data => {
                  if (data.code !== 200) {
                      message.error(data.message)
                      return
                  }
                  message.success(data.message)
                  getData()
              }
          )
      }

      //     任务开始
      function handleOpen(record) {
          record.startLoading = true
          if (record.instanceId) {
              message.info('请审批完成后再开始任务')
              return
          }
          if (record.taskType === '问题') {
              put('/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/task_and_problem_status_change', {
                  'id': record.taskId,
                  'status': '开始',
                  'solver': ''
              })
                  .then(data => {
                      if (data.code !== 200) {
                          message.error(data.message)
                          return
                      }
                      message.success(data.message)
                      getData()
                  })
                  .finally(() => {
                      record.startLoading = false
                  })
          } else {
              put(`/solution-ppm/api/v2/built-in-system-ppm/refactoring_task/start_task/${record.taskId}`)
                  .then(data => {
                      if (data.code !== 200) {
                          message.error(data.message)
                          return
                      }
                      message.success(data.message)
                      getData()
                  })
                  .finally(() => {
                      record.startLoading = false
                  })
          }
      }
      // 恢复
      function restore(item) {
          put('/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/task_and_problem_status_change', {
              'id': item.taskId,
              'status': '恢复',
              'solver': ''
          })
              .then(data => {
                  if (data.code !== 200) {
                      message.error(data.message)
                      return
                  }
                  message.success(data.message)
                  getData()
              })
              .finally(() => {
                  templateOkDisabled.value = false
              })
      }
      //     任务完成
      function beforeOkMb(record) {
          if (record.taskStatus === '测试中') {
              message.info('请联系测试经理发起验收后再试')
              return
          }
          if (record.taskType === '问题') {
              if (record.taskStatus === '审批中' || record.taskStatus === '延期完成' || record.taskStatus === '完成') {
                  message.error(`问题状态为${record.taskStatus}的任务无法进行完成操作`)
                  return
              }
              templateOkDisabled.value = true
              put('/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/task_and_problem_status_change', {
                  'id': record.taskId,
                  'status': '完成',
                  'solver': ''
              })
                  .then(data => {
                      if (data.code !== 200) {
                          message.error(data.message)
                          return
                      }
                      message.success(data.message)
                      getData()
                  })
                  .finally(() => {
                      templateOkDisabled.value = false
                  })
          } else {
              if (record.taskStatus === '审批中' || record.taskStatus === '延期完成' || record.taskStatus === '完成') {
                  message.error(`问题状态为${record.taskStatus}的任务无法进行完成操作`)
                  return
              }
              // 任务的完成
              if (record.taskType === 'SOP任务' || record.taskType === '子任务') {
                  currentOkTask.value = record
                  // 新-获取审核标准赋值
                  get(
                      `/solution-ppm/api/v2/built-in-system-ppm/v2/platform/${currentOkTask.value.taskId}/assessor_standard_and_sop/search`
                  ).then(data => {
                      taskState.ppmTemplateCheckList =
                          data.data.assessorStandardList?.map(item => {
                              return {
                                  type: item.type,
                                  selected: item.selected,
                                  content: item.content
                              }
                          }) || []
                      taskState.sopList = data.data.sopList
                      if (data.data.finishStandard !== null) {
                          taskState.CompletionCheckListCheckList = data.data.finishStandardList
                      } else {
                          taskState.CompletionCheckListCheckList = []
                      }
                      get(`/solution-ppm/api/v2/built-in-system-ppm/v2/platform/task/attachment/${record.taskId}`).then(
                          ({ data }) => {
                              taskState.fileList = data?.attachment ? JSON.parse(data.attachment) : []
                              taskState.okMbVisible = true
                          }
                      )
                  })
              } else {
                  //     问题的完成
              }
          }
      }
      //   格式化文本展示
      import { QuillDeltaToHtmlConverter } from 'quill-delta-to-html'
      function getHtmlContent(input) {
          if (!input) return ''
          let deltaObj = null
          try {
              const parsed = typeof input === 'string' ? JSON.parse(input) : input
              if (parsed?.ops && Array.isArray(parsed.ops)) {
                  deltaObj = parsed
              }
          } catch (e) {}

          if (deltaObj) {
              try {
                  const converter = new QuillDeltaToHtmlConverter(deltaObj.ops, {
                      inlineStyles: false
                  })
                  let html = converter.convert()

                  // 预览支持：用原生 <img> 包裹在一个带点击预览功能的 <a> 中
                  html = html.replace(/<img[^>]*src="([^"]+)"[^>]*>/g, (match, src) => {
                      return `<img src="${src}" class="previewable-image" title="点击查看图片"/>`
                  })

                  return html
              } catch (err) {
                  console.error('富文本转HTML失败', err)
                  return ''
              }
          }

          return String(input).replace(/\n/g, '<br/>')
      }
      //     展示附件
      const fileShowList = ref([])
      const showFileVisible = ref(false)
      function showMore(data) {
          fileShowList.value = data
          showFileVisible.value = true
      }
      function showFileCancel() {
          fileShowList.value = []
          showFileVisible.value = false
      }
      // 模板项目附件模板下载
      function handlerDownload(item) {
          fetch(item.url)
              .then(response => response.blob())
              .then(blob => {
                  const downloadLink = document.createElement('a')
                  const url = URL.createObjectURL(blob)
                  downloadLink.href = url
                  downloadLink.setAttribute('download', item.name)
                  downloadLink.style.display = 'none'
                  document.body.appendChild(downloadLink)
                  downloadLink.click()
                  document.body.removeChild(downloadLink)

                  // Release the object URL after the download
                  URL.revokeObjectURL(url)
              })
              .catch(err => {
                  console.error('Download failed', err)
              })
      }
      // 图片预览

      const stateF = reactive({
          previewVisible: false,
          previewImage: '',
          previewFileUrl: '',
          isImagePreview: false
      })
      function previewAttachment(item) {
          // 检查附件类型
          if (item.type.startsWith('image')) {
              stateF.isImagePreview = true
              stateF.previewImage = item.url // 设置预览图片的URL
              stateF.previewVisible = true // 显示模态框
          } else {
              // stateF.isImagePreview = false;
              // // 如果是其他类型的文件，直接在模态框中显示
              // stateF.previewFileUrl = item.url; // 设置预览文件的URL
              message.info('目前仅支持图片预览')
          }
      }
      // 任务下载全部模板
      function downLoadTemplate() {
          if (currentOkTask.value.attachmentTemplateList.length < 1) {
              message.info('任务没有附件')
          } else {
              post(
                  `/solution-ppm/api/v2/built-in-system-ppm/delivery_task/download_template/${currentOkTask.value.taskId}`,
                  null,
                  { responseType: 'arraybuffer' }
              ).then(res => {
                  downloadZip(res, '任务附件模板.zip')
              })
          }
      }
      function downloadZip(response, name) {
          const blob = new Blob([response], { type: 'application/zip;charset=utf-8' })
          const downloadElement = document.createElement('a')
          const href = window.URL.createObjectURL(blob)
          downloadElement.href = href
          downloadElement.download = name // 下载后文件名
          document.body.appendChild(downloadElement)
          downloadElement.click()
          document.body.removeChild(downloadElement)
          window.URL.revokeObjectURL(href)
          return href
      }
      const uploadLoading = ref(false)
      function handlerUploadWc(file) {
          uploadLoading.value = true
          const data = new FormData()
          data.append('file', file)

          post('/file-storage/api/v1/file/upload', data)
              .then(({ data: { fullUrl } }) => {
                  if (data) {
                      taskState.fileList = [
                          ...taskState.fileList,
                          {
                              uid: file.uid,
                              lastModified: file.lastModified,
                              name: file.name,
                              size: file.size,
                              type: file.type,
                              status: 'done',
                              url: fullUrl
                          }
                      ]
                  }
              })
              .finally(() => {
                  uploadLoading.value = false
              })
          return false
      }

      function handleRemoveWc(file) {
          taskState.fileList = taskState.fileList.filter(item => item.uid !== file.uid)
      }
      // 暂存sop
      function handleSubmitSop() {
          const params = {
              form: [],
              sopList: taskState.sopList,
              taskId: currentOkTask.value.taskId
          }
          params.form = [...taskState.CompletionCheckListCheckList, ...taskState.ppmTemplateCheckList]
          post('/solution-ppm/api/v2/built-in-system-ppm/delivery_task/save_standard_sop', params).then(() => {
              message.success('操作成功')
              taskState.okMbVisible = false
              getData()
          })
      }
      // 新-新模板项目检查清单确认事件
      const templateOkDisabled = ref(false)
      function handlerTemplateOk() {
          if (!checkAllSelected(taskState.sopList[0].contentList)) {
              message.info('请确认完成标准及SOP全部已实现')
          } else {
              handlerCheckOk()
          }
      }
      function checkAllSelected(content) {
          for (let i = 0; i < content.length; i++) {
              if (!content[i].selected) {
                  return false // 只要有一个 selected 不为 true，就返回 false
              }
          }
          return true // 如果所有的 selected 都为 true，返回 true
      }
      function handlerCheckOk() {
          templateOkDisabled.value = true
          const params = {
              form: [],
              sopList: taskState.sopList,
              taskId: currentOkTask.value.taskId
          }
          params.form = [...taskState.CompletionCheckListCheckList, ...taskState.ppmTemplateCheckList]
          post('/solution-ppm/api/v2/built-in-system-ppm/v2/platform/task/attachment', {
              ppmEnclosureInfoList: taskState.fileList,
              taskId: currentOkTask.value.taskId
          }).then(data => {
              if (data.code === 200) {
                  post('/solution-ppm/api/v2/built-in-system-ppm/delivery_task/save_standard_sop', params).then(() => {
                      if (data.code === 200) {
                          put('/solution-ppm/api/v2/built-in-system-ppm/v2/platform/task/status', {
                              taskId: currentOkTask.value.taskId
                          })
                              .then(data => {
                                  if (data.code !== 200) {
                                      message.error(data.message)
                                      templateOkDisabled.value = false
                                      return
                                  }
                                  templateOkDisabled.value = false
                                  taskState.okMbVisible = false
                                  message.success('操作成功')
                                  getData()
                              })
                              .finally(() => {
                                  templateOkDisabled.value = false
                              })
                      } else {
                          message.error('提交失败')
                          templateOkDisabled.value = false
                      }
                  })
              } else {
                  templateOkDisabled.value = false
                  message.error('附件上传失败')
              }
          })
      }
      function confirmDeleteQuestion(record) {
          if (record.taskFinishTime) {
              message.info('已完成的任务不支持删除')
              return
          } else if (record.taskStatus === '审批中') {
              message.info('审批中的任务不支持删除')
              return
          }
          del(` /solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/problem/${record.taskId}`).then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  return
              }
              message.success(data.message)
              getData()
          })
      }
      function confirmDeleteTask(record) {
          if (record.taskFinishTime) {
              message.info('已完成的任务不支持删除')
              return
          } else if (record.taskStatus === '审批中') {
              message.info('审批中的任务不支持删除')
              return
          }
          del('/solution-ppm/api/v2/built-in-system-ppm/v2/platform/task/approve', {
              data: {
                  plName: record.plName,
                  taskId: record.taskId
              }
          }).then(({ code, message: errorMsg }) => {
              if (code === 200) {
                  message.success('提交成功')
                  getData()
              } else {
                  message.error(errorMsg || '删除失败')
              }
          })
      }
      //     提测验收
      const currentCheckData = ref({})
      const checkFlag = ref('')
      function handleCheck(item, flag) {
          currentCheckData.value = item
          checkFlag.value = flag
          taskState.checkVisible = true
          taskState.checkTitle = `确认${flag}`
      }
      const currentCirculationData = ref({})
      // 流转
      function showCirculation(record, flag) {
          currentCirculationData.value = record
          taskState.culaVisible = true
      }
      function handleSubmitCirculation() {
          taskState.culaLoading = true
          put('/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/task_and_problem_status_change', {
              id: currentCirculationData.value.taskId,
              status: '流转',
              solver: taskState.culaPeople
          })
              .then(data => {
                  if (data.code !== 200) {
                      message.error(data.message)
                      return
                  }
                  message.success(data.message)
                  cancelCirculation()
                  getData()
              })
              .finally(() => {
                  taskState.culaLoading = false
              })
      }
      function cancelCirculation() {
          taskState.culaPeople = undefined
          taskState.culaVisible = false
          currentCirculationData.value = {}
      }
      function handleSubmitCheck() {
          taskState.checkLoading = true
          put('/solution-ppm/api/v2/built-in-system-ppm/v3/platform_task/task_and_problem_status_change', {
              id: currentCheckData.value.taskId,
              status: checkFlag.value === '提测' ? '测试中' : '验收中'
          })
              .then(data => {
                  if (data.code !== 200) {
                      message.error(data.message)
                      return
                  }
                  message.success(data.message)
                  cancelCheck()
                  getData()
              })
              .finally(() => {
                  taskState.checkLoading = false
              })
      }
      function cancelCheck() {
          taskState.checkVisible = false
          currentCheckData.value = {}
          checkFlag.value = ''
      }
      // 模板项目-风险预警
      const warnState = reactive({
          warringVisible: false,
          templateRisk: {
              taskId: undefined,
              taskName: undefined,
              riskDescription: undefined,
              milepostId: undefined,
              projectId: undefined,
              solution: undefined
          }
      })
      function handlerWarning(record) {
          if (!record.taskOwnerPermission) {
              message.error('非该任务任务负责人')
          } else {
              if (record.taskFinishTime !== null) {
                  message.info('该任务已完成，此功能已关闭')
              } else {
                  get(`/solution-ppm/api/v2/built-in-system-ppm/permission/ppyj/create`).then(({ data }) => {
                      if (data === false) {
                          message.info('暂无权限')
                      } else {
                          warnState.warringVisible = true
                          warnState.templateRisk.taskName = record.taskName
                          warnState.templateRisk.riskDescription = record.riskDescription
                          warnState.templateRisk.solution = record.solution
                          warnState.templateRisk.taskId = record.taskId
                          warnState.templateRisk.projectId = record.projectId
                          warnState.templateRisk.milepostId = record.milepostId
                      }
                  })
              }
          }
      }
      const templateRiskRef = ref(null)
      // 模板项目风险保存
      function handleTemplateRiskOk() {
          templateRiskRef.value.validate().then(() => {
              const params = {
                  taskId: warnState.templateRisk.taskId,
                  projectId: warnState.templateRisk.projectId,
                  milepostId: warnState.templateRisk.milepostId,
                  riskDescription: warnState.templateRisk.riskDescription,
                  solution: warnState.templateRisk.solution
              }
              post('/solution-ppm/api/v2/built-in-system-ppm/refactoring_task/task_warn', params).then(data => {
                  if (data.code === 200) {
                      message.success('操作成功')
                      warnState.warringVisible = false
                      getData()
                  } else {
                      message.error(data.message)
                  }
              })
          })
      }
      // 历史备注
      const noteState = reactive({
          visibleNotes: false,
          noteData: undefined,
          notesColumns: [
              { title: '备注内容', dataIndex: 'description', align: 'center' },
              { title: '提交人', dataIndex: 'createdBy', align: 'center', width: '200px' },
              { title: '提交时间', dataIndex: 'submissionTime', align: 'center', width: '200px' }
          ]
      })
      function handlerShowNotes(record) {
          post('/solution-ppm/api/v2/built-in-system-ppm/description/queryDescription', {
              sourceId: record.taskId,
              descriptionType: 'TASK'
          }).then(({ data }) => {
              noteState.noteData = data
              console.log(noteState.noteData.descriptionDataList)
              noteState.visibleNotes = true
          })
      }
      function getStatusList() {
          statusRadio.value = '状态变更'
          get('/solution-ppm/api/v2/built-in-system-ppm/dictionary/search/PTRW.RWZT').then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  return
              }
              taskState.statusList = data.data.map(item => {
                  return {
                      label: item.itemName,
                      value: item.itemCode
                  }
              })
          })
      }
      //     审批记录以及更换状态
      const statuState = reactive({
          visible: false,
          list: [],
          taskType: undefined,
          taksName: undefined
      })
      function getTaskStatus(id, type, mileId, status, taskType, item) {
          statuState.taskType = taskType
          statuState.taskName = item.taskName
          get(`/solution-ppm/api/v2/built-in-system-ppm/refactoring_task/task_approval_detail/${id}/${type}    `).then(
              data => {
                  if (data.code !== 200) {
                      message.error(data.message)
                      return
                  }
                  statuState.visible = true
                  if (mileId) {
                      get(`/solution-ppm/api/v2/built-in-system-ppm/v2/platform/get_template_task_status/${mileId}`).then(
                          data2 => {
                              if (data2.code !== 200) {
                                  message.error(data2.message)
                                  return
                              }
                              statusList.value = data2.data
                          }
                      )
                  }
                  statusList.value = []
                  statusCurrentId.value = id
                  statusCheckList.value = status
                  statuState.list = data.data
                  statusRadio.value = '状态变更'
              }
          )
      }

      const statusCurrentId = ref(null)
      const statusRadio = ref('状态变更')
      const statusList = ref([])
      const statusCheckList = ref('')
      function handleConfirmStatus() {
          if (statuState.taskType === '问题') {
              message.info('问题不支持自定义状态')
              return
          }
          put(
              ` /solution-ppm/api/v2/built-in-system-ppm/v2/platform/modify_task_status/${statusCurrentId.value}/${statusCheckList.value}`
          ).then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  return
              }
              message.success(data.message)
              statuState.visible = false
              statusRadio.value = '状态变更'
              getData()
          })
      }

      // 判断按钮是否可用的计算属性
      function isCirculationDisabled(item) {
          return !item.solverManagerPermission || item.taskStauts === '完成' || item.taskStauts === '延期完成'
      }
      // 开始按钮禁用状态
      function openDisabled(item) {
          if (item.taskStatus && item.taskStatus === '审批中') {
              return true
          }
          if (item.taskType === '问题') {
              // 问题由解决人开启，非解决人禁用
              if (!item.solverManagerPermission) {
                  return true
              } else {
                  return false
              }
          } else {
              // 其他类型问题由任务负责人开启
              if (!item.taskOwnerPermission) {
                  return true
              } else {
                  return false
              }
          }
      }
      //     编辑按钮禁用状态
      function disabledEditBtn(item) {
          if (item.taskStatus && item.taskStatus === '审批中') {
              return true
          }
          if (item.taskType === '问题') {
              // 问题由解决人开启，非解决人禁用
              if (!item.testManagerPermission) {
                  return true
              } else {
                  return false
              }
          } else {
              return false
          }
      }
      //     新建问题禁用状态
      function addQuestionDisabled(item) {
          // return !item.testManagerPermission
          return false
      }

      //完成按钮禁用 TODO:补充非开发和开发
      function disabledComplate(item) {
          if ((item.taskStatus && item.taskStatus === '审批中') || item.taskFinishTime) {
              return true
          }
          if (item.taskType === '问题') {
              if (!item.solverManagerPermission) {
                  return true
              } else {
                  return false
              }
          } else {
              // 如果任务目前是提测和验收状态就是产品经理点完成。否则是任务任务负责人
              if (item.taskStatus === '验收中' || item.taskStatus === '测试中') {
                  if (!item.productManagerPermission) {
                      return true
                  } else {
                      return false
                  }
              } else {
                  if (!item.taskOwnerPermission) {
                      return true
                  } else {
                      return false
                  }
              }
          }
      }
      // 恢复
      //完成按钮禁用 TODO:补充非开发和开发
      function disabledRestore(item) {
          if (item.taskStatus && item.taskStatus === '审批中') {
              return true
          }
          // 其他类型问题由任务负责人开启
          if (!item.testManagerPermission) {
              return true
          } else {
              return false
          }
      }
      //     提测禁用
      function testImprovementDisabled(item) {
          if (item.taskStatus && item.taskStatus === '审批中') {
              return true
          }
          if (!item.taskOwnerPermission || !item.examPassTime) {
              return true
          } else {
              return false
          }
      }
      //     验收禁用
      function checkDisabled(item) {
          if (item.taskStatus && item.taskStatus === '审批中') {
              return true
          }
          if (!item.testManagerPermission || !item.examPassTime) {
              return true
          } else {
              return false
          }
      }
      function handleExpendAll() {
          console.log(taskState.expendAll)
          if (taskState.expendAll) {
              taskState.expendAll = false
              taskState.dataList.forEach(item => {
                  item.expend = false
              })
          } else {
              taskState.expendAll = true
              taskState.dataList.forEach(item => {
                  item.expend = true
              })
          }
      }
      const validatePriority = (rule, value) => {
          if (value === undefined || value === null || value === '') {
              return Promise.reject(new Error('请输入优先级'))
          }
          const number = Number(value)
          const isValid = number > 0 && number < 100 && /^(\d{1,2})(\.\d)?$/.test(value.toString())
          return isValid ? Promise.resolve() : Promise.reject(new Error('请输入 1 到 99 之间，最多一位小数的正数'))
      }
      function handlerGetSpace(data) {
          return data?.split(/[,;；]/)
      }
      //     关键路径改

      function initKeynotes(list) {
          initialKeynotes.clear() // 清空旧的
          list.forEach(item => {
              initialKeynotes.set(item.taskId, item.keynote)
          })
      }

      const modifiedKeynotes = reactive(new Map()) // key: taskId, value: '是' or '否'
      const initialKeynotes = new Map()
      function handlerShowCheck() {
          console.log('触发')
          if (!taskState.showCheck) {
              taskState.showCheck = true
          } else {
              const checkedList = Array.from(modifiedKeynotes.entries())
                  .filter(([_, val]) => val === '是')
                  .map(([taskId]) => taskId)

              taskState.keyNoteLoading = true
              const added = []
              const removed = []
              modifiedKeynotes.forEach((val, taskId) => {
                  const original = initialKeynotes.get(taskId)
                  if (original !== val) {
                      if (val === '是') added.push(taskId)
                      else removed.push(taskId)
                  }
              })
              put(`/solution-ppm/api/v2/built-in-system-ppm/v2/platform/keynote_task/${useProjectId.value}`, {
                  addedKeynotes: added,
                  removedKeynotes: removed
              })
                  .then(data => {
                      if (data.code !== 200) {
                          message.error(data.message)
                          return
                      }
                      message.success(data.message)
                      taskState.showCheck = false
                      modifiedKeynotes.clear() // 提交后清除记录
                      getData()
                  })
                  .finally(() => {
                      taskState.keyNoteLoading = false
                  })
          }
      }

      const getIconStatus = status => {
          if (status === 'finish') {
              return 'finish'
          } else if (status === 'process') {
              return 'process'
          } else {
              return 'error'
          }
      }
      //     新筛选
      const tabsConfig = {
          all: {
              label: '全部任务',
              children: [{ label: '全部任务', key: 'all' }]
          },
          notStarted: {
              label: '未启动',
              children: [
                  { label: '全部任务', key: 'all' },
                  { label: '正常未启动', key: '正常未启动' },
                  { label: '延期未启动', key: '延期未启动' }
              ]
          },
          inProgress: {
              label: '进行中',
              children: [
                  { label: '全部任务', key: 'all' },
                  { label: '正常进行中', key: '正常进行中' },
                  { label: '延期进行中', key: '延期进行中' }
              ]
          },
          testing: {
              label: '测试中',
              children: [
                  { label: '全部任务', key: 'all' },
                  { label: '正常测试中', key: '正常测试中' },
                  { label: '延期测试中', key: '延期测试中' }
              ]
          },
          accepting: {
              label: '验收中',
              children: [
                  { label: '全部任务', key: 'all' },
                  { label: '正常验收中', key: '正常验收中' },
                  { label: '延期验收中', key: '延期验收中' }
              ]
          },
          completed: {
              label: '完成',
              children: [
                  { label: '全部任务', key: 'all' },
                  { label: '正常完成', key: '正常完成' },
                  { label: '延期完成', key: '延期完成' }
              ]
          }
      }

      // 当前激活的顶部tab
      const activeTopTab = ref('all')

      // 每个顶部tab对应的子tab key（默认选第一个）
      const activeSubTab = reactive(Object.fromEntries(Object.keys(tabsConfig).map(key => [key, 'all'])))
      // 当前 tab 下的子项 options（用于 Select）
      const currentSubTabOptions = computed(() => {
          return (tabsConfig[activeTopTab.value]?.children || []).map(item => ({
              label: item.label,
              value: item.key
          }))
      })

      // 筛选值（传给接口）
      const filterStatus = computed(() => {
          const top = activeTopTab.value
          const sub = activeSubTab[top]

          if (sub === 'all') {
              return tabsConfig[top].children.filter(item => item.key !== 'all').map(item => item.key)
          } else {
              return [sub]
          }
      })

      // 顶部 tab 切换
      function onTopTabChange(topKey) {
          activeTopTab.value = topKey
          if (!activeSubTab[topKey]) {
              activeSubTab[topKey] = 'all'
          }
          getData()
      }
      // 下拉筛选变更
      function onSubTabChange(subKey) {
          activeSubTab[activeTopTab.value] = subKey
          getData()
      }
      const showMsgState = reactive({
          visible: false,
          msg: undefined,
          title: ''
      })
      function showQuestionMsg(msg) {
          showMsgState.msg = msg
          showMsgState.visible = true
      }
      function cancelShowMsg() {
          showMsgState.msg = undefined
          showMsgState.visible = false
      }
      function getBgc(type) {
          if (type === 'P0') {
              return '#FF4D4F'
          } else if (type === 'P1') {
              return '#FF7A45'
          } else if (type === 'P2') {
              return '#FFA940'
          } else if (type === 'P3') {
              return '#FFC53D'
          }
      }
</script>
<style lang="less" scoped>
  .page_root {
  width: 100%;
  height: 100%;
  overflow: auto;
  }
  .page_root :deep(.@{ant-prefix}-spin-nested-loading),
  .page_root :deep(.@{ant-prefix}-spin-container)
   {
      height: 100%;
  }
  .page_root :deep(.@{ant-prefix}-spin-container .@{ant-prefix}-table-wrapper)
   {
      display: flex;
      flex-flow: column nowrap;
      justify-content: flex-start;
  }
  .page_root :deep(.@{ant-prefix}-table)
   {
    flex: auto;
    overflow: auto;
  }
  .table-moreBtn_down {
    overflow: hidden; white-space: nowrap; text-overflow: ellipsis; width: 100px;
  }

  .table-moreBtn_menu :deep(.table-moreBtn_menu-item):hover {
    background: #ebf1ff;
  }

  /*  表格树结构样式处理，展开按钮层级增加*/
  :deep(.@{ant-prefix}-table-row-expand-icon) {
    z-index: 1;
  }
  /*  表格树结构 由于每个表格项采用自定义组件，使用绝对定位布局，开启树结构导致显示异常，暂时使用层级定位位置 */
  :deep(.@{ant-prefix}-table-row-level-1 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
    left: 15px !important;
    width: calc(100% - 15px);
  }
  :deep(.@{ant-prefix}-table-row-level-2 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
    left: 30px !important;
    width: calc(100% - 30px);
  }
  :deep(.@{ant-prefix}-table-row-level-3 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
    left: 45px !important;
    width: calc(100% - 45px);
  }
  :deep(.@{ant-prefix}-table-row-level-4 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
    left: 60px !important;
    width: calc(100% - 60px);
  }

  /* 穿梭框改变默认样式，为根据组件样式控制左右栏宽度。 */
  :deep(.@{ant-prefix}-transfer-list)
   {
      height: 100%;
      width: 50%;
  }
  .vid_rw9kkee3ys{
      padding-top:24px;
      padding-bottom:24px;
      background-color:#EE0B0B
  }
  .vid_tpphoipqc8{
      box-shadow:0px 0px 0px 0px
  }
  .vid_uomosqlhjq{
      box-shadow:0px 0px 0px 0px
  }

  .content {
    position: relative;
    height: calc(100vh - 400px);
    overflow-y: auto;
  }
  .no-progress {
    height: 370px;
    width: 100%;
    background-color: #fff;
    display: flex;
    justify-content: center;
    border: 1px solid #fff;
    border-radius: 10px;
    position: relative;
    /* 水平居中 */
  }
  .no-progress .no-tip {
    width: 200px;
    height: 101px;
    background-image: url('@/assets/images/903bc3976708306bda3d72329b485333.png');
    background-size: cover;
    position: absolute;
    top: 30%;
    color: rgb(89, 89, 89);
  }
  .no-progress .no-tip .message {
    position: absolute;
    left: 35%;
    bottom: -40px;
    font-size: 14px;
    color: rgb(89, 89, 89);
  }
  .form-model :deep(.ant3-form-item-label) {
    width: 110px;
  }
  .story-item {
    background: #ffffff;
    //box-shadow: 0 2px 5px 0  #f2f6fc;
    border-radius: 4px;
    margin: 1px 1px 16px 1px;
  }
  .story-title {
    display: flex;
    justify-content: space-between;
    background:linear-gradient(to bottom, rgba(255,255,255,.92), #fff, #fff);
    border-radius:   0;
    padding: 17px 24px;
    gap: 16px;
    align-items: center;
    cursor: pointer;

  }
  .title-right {
  }
  .title-left {
    font-size: 16px;
    color: #262626;
    font-weight: 600;
    align-items: center;
    flex: 1;
    min-width: 0;

  }
  .title-left-mains{
    display: flex;
    gap: 8px;
    margin-bottom: 4px;
  }
  .title-left-tags{
    display: flex;
    gap: 8px;
    align-items: center;
  }
  .tags-group{
    display: flex;
    gap: 8px;
    font-size: 12px;
    align-items: center;
    color:#999;
    font-weight: 400;

    .target-icon{
      width: 12px;
      height: 12px;
      margin-left: 4px;
    }

  }

  .task-name {
    font-size: 15px;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    min-width: 0;
  }
  .type-tag{
    background: #fff;
    flex:1;
    flex-shrink: 0;
  }

  .priority-tag {
    min-width: 32px;
    height: 22px;
    color: #fff;
    text-align: center;
    line-height: 22px;
    font-weight: 600;
    font-style: oblique;
    letter-spacing: 1px;
    overflow: hidden;
  }
  .status-tag,
  .type-tag,
  .priority-tag {
    font-size: 14px;
    color: #ffffff;
    letter-spacing: 0;
    text-align: center;
    line-height: 22px;
    font-weight: 500;
    height: 22px;
    text-align: center;
    padding: 0 4px;
  }
  .status-tag {
    cursor: pointer;
    min-width: 72px;
    display: flex;
    align-items: center;
    gap: 12px;
    flex: 1;
    justify-content: center;
    padding:0 10px;
    box-shadow: 0 2px 6px #d3d8df;
  }
  .can-edit {
    width: 16px;
    height: 16px;
    background-image: url('@/assets/images/bcf74a5ffa486288cc59a4cdfefd3363.png');
    background-size: cover;
    opacity: 0.7;
  }
  .story-content {
    padding: 16px 24px;
    background: #fff;
  }
  .one-line,
  .two-line,
  .three-line,
  .four-line {
    display: flex;
    gap: 24px;
    align-items: center;
  }
  .one-line,
  .two-line,
  .three-line {
    margin-bottom: 12px;
  }
  .row-item {
    flex: 1 1 calc((100% - 5 * 24px) / 6); /* 每行 6 项，5 个间距 */
    display: flex;
    flex-direction: row;
    min-width: 0;
  }
  .item-title {
    white-space: nowrap;
    margin-bottom: 4px;
    font-size: 14px;
    color: #595959;
    letter-spacing: 0;
    text-align: right;
    font-weight: 400;
  }
  .item-content {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    cursor: default;
    font-family: PingFangSC-Medium;
    font-size: 14px;
    color: #262626;
    letter-spacing: 0;
    font-weight: 600;
  }
  .no-set {
    max-width: none;
  }
  .mbtask-form :deep(.ant3-form-item-label) {
    width: 115px !important;
  }
  .question-form :deep(.ant3-form-item-label) {
    width: 115px !important;
  }
  .main-font {
    color: #3875ff;
    cursor: pointer;
  }
  .under-line {
    text-decoration: underline;
  }
  :deep(.ql-toolbar) {
    background: #fafafa;
    border: 1px solid #d9d9d9;
    border-radius:  0;
  }
  :deep(.ql-blank) {
    min-height: 110px;
    background: #ffffff;
  }
  :deep(.ql-editor) {
    min-height: 110px;
    background: #ffffff;
  }
  .new-check .label {
    font-size: 16px;
    line-height: 1.4em;
    color: #3875ff;
    border-left: 6px solid #3875ff;
    text-indent: 8px;
    margin: 8px 0;
  }
  .file-item {
    cursor: pointer;
  }
  .critical-path {
    color: #999;
    border-left: 1px solid #aaa;
    padding-left: 12px;
    margin-left: 10px;
    font-size: 12px;
    height: 12px;
    line-height: 12px;
    font-weight: 400;
    position: relative;

    &:before{
      content: '';
      position: absolute;
      left: 33px;
      top: 3px;
      width: 6px;
      height: 6px;
      border-radius: 50%;
      background: #8b9bef;
    }
  }

  .note-table :deep(.@{ant-prefix}-table-thead) > tr > th {
    background: #3875ff;
    font-size: 14px;
    font-family: arial, helvetica, 'microsoft yahei';
    font-weight: 600;
    color: #ffffff;
    border-bottom: 1px solid #3875ff;
    padding: 8px 16px;
  }
  .slide-fade-enter-active,
  .slide-fade-leave-active {
    transition: all 0.3s ease;
    overflow: hidden;
  }
  .slide-fade-enter-from,
  .slide-fade-leave-to {
    max-height: 0;
    opacity: 0;
  }
  .slide-fade-enter-to,
  .slide-fade-leave-from {
    max-height: 500px; /* 根据内容大小调整 */
    opacity: 1;
  }
  .item-icon {
    display: flex;
    flex-wrap: wrap;
    gap: 8px; /* 可选：让 tag 之间有间距 */
    //margin-top: 16px;
    padding: 0 24px;
  }
  .label-item {
    display: flex;
    background-color: #eeeeee;
    align-items: center;
    padding: 1px 8px;
    ont-size: 14px;
    color: #595959;
    letter-spacing: 0;
    text-align: center;
    font-weight: 400;
    gap: 4px;
    border-radius: 0;
  }
  .label-img {
    background-image: url('@/assets/images/41210ac3a80806ed1005d4eea85d458a.png');
    background-size: cover;
    width: 10px;
    height: 10px;
  }
  .priority-tag {
    background: #ccc;
    border-radius: 0;
  }
  .table-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-bottom: 16px;
    box-shadow: 0 2px 8px #f2f6f2;
    margin-bottom: 6px;
  }
  .tip {
    font-size: 16px;
    color: #262626;
    letter-spacing: 0;
    font-weight: 600;
    line-height: 16px;
    border-left: 4px solid #3875ff;
    padding-left: 8px;
    height: 16px;
  }
  .top-search :deep(.ant3-form-item) {
    margin-bottom: 16px;
  }
  .reset-btn {
    color: #262626;
    background-color: #eeeeee;
    border-color: #eeeeee;
    border-radius: 4px;
  }
  .reset-btn:hover {
    background: #3875ff;
    border-color: #d9d9d9;
    color: #fff;
  }
  .btn-opration {
    /* background-color: #ebf1ff;
    color: #3875ff; */
  }
  .title-right :deep(.ant3-btn) {
    padding: 0;
  }

  .title-new-status {
    height: 62px;
    line-height: 36px;
    padding: 0 16px;
    margin-bottom: 16px;
    background-image: url('@/assets/images/18c5598e33c9488e1925bf0bd3b80ebb.png');
    background-size: cover;
    border: 1px solid #3875ff;
    border-radius: 5px;
  }

  :deep(.ant3-steps-item-container) {
    padding: 0 16px;
  }
  :deep(.ant3-steps-item-tail::after) {
    margin-left: 12px;
    background-color: #3875ff;
  }
  :deep(.ant3-steps-item-description) {
    font-size: 12px;
    color: #595959;
    text-align: left;
    line-height: 20px;
    font-weight: 400;
  }
  :deep(.ant3-steps-item-icon) {
    width: 24px;
    height: 24px;
    line-height: 24px;
    color: #3875ff;
    margin-top: 6px;
  }
  :deep(.ant3-steps-item-title) {
    height: 28px;
    font-size: 14px;
    color: #262626;
    text-align: left;
    line-height: 22px;
    font-weight: 400;
  }
  :deep(.ant3-steps-item-process > .ant3-steps-item-container > .ant3-steps-item-icon) {
    background-color: #3875ff;
  }
  :deep(.ant3-steps-vertical > .ant3-steps-item > .ant3-steps-item-container > .ant3-steps-item-tail::after) {
    background: #3875ff;
  }
  :deep(.status-step .ant3-steps-vertical > .ant3-steps-item .ant3-steps-item-icon) {
    border-color: #3875ff;
  }
  :deep(.ant3-steps-item-finish .ant3-steps-item-icon > .ant3-steps-icon) {
    color: #3875ff !important;
  }
  .task-status-new {
    cursor: pointer;
    text-align: left;
  }
  .left-title,
  .right-title {
    font-size: 14px;
    color: rgba(0, 0, 0, 0.65);
    letter-spacing: 0;
    text-align: left;
    font-weight: 400;
    height: 31px;
    line-height: 31px;
  }
  .weight-status {
    font-size: 14px;
    color: #262626;
    letter-spacing: 0;
    font-weight: 500;
  }
  .batch-line {
    width: 100%;
    border-top: 1px solid #d9d9d9;
    margin: 16px 0;
  }
  .weight-status-new {
    font-weight: 600;
    color: #262626;
  }
  .top-search :deep(.ant3-form-item-label) {
    width: 95px;
  }
  .tab-body {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
  }
  .tab-buttons {
    display: flex;
    gap: 8px;
  }

  .tab-btn {
    background: #f2f2f2;
    border-radius: 4px;
    font-size: 14px;
    color: #595959;
    letter-spacing: 0;
    text-align: center;
    font-weight: 400;
    padding: 5px 16px;
    cursor: pointer;
  }

  .tab-btn.active {
    background: rgba(56, 117, 255, 0.1);
    border-radius: 4px;
    color: #3875ff;
    letter-spacing: 0;
    text-align: center;
    font-weight: 600;
  }
  :deep(.ant3-descriptions-item-label) {
    text-align: right;
  }
  :deep(.ant3-descriptions-view) {
    table {
      table-layout: fixed !important; /* 固定表格布局 */
      width: 100% !important;
      color: red;
    }
  }
  :deep(.ant3-descriptions-item-label),
  :deep(.ant3-descriptions-item-content) {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .target-item {
    align-items: center;
  }
  .target-icon {
    width: 16px;
    height: 16px;
    background-image: url('@/assets/images/5457dd41e8ffbba86c21cec0f78e4349.png');
    background-size: cover;
  }
  .story-icon {
    width: 16px;
    height: 16px;
    background-image: url('@/assets/images/330f3cd64fe1884fa32afbd1d97374ef.png');
    background-size: cover;
  }
</style>